Skip to content

Commit

Permalink
Add cel for forbidden-sysctls
Browse files Browse the repository at this point in the history
Signed-off-by: Rita Zhang <[email protected]>
  • Loading branch information
ritazh committed Dec 14, 2024
1 parent 52cb14a commit 386428f
Show file tree
Hide file tree
Showing 18 changed files with 810 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Forbidden Sysctls security context policy

The forbidden sysctls constraint allows one to limit the set of kernel parameters that can be modified by pods. This is accomplished by specifying a combination of allowed and forbidden sysctls using either of two parameters: `allowedSysctls` and `forbiddenSysctls`.

## Parameters

`allowedSysctls`: A list of explicitly allowed sysctls. Any sysctl not in this list will be considered forbidden. '*' and trailing wildcards are supported. If unspecified, no limitations are made by this parameter.

`forbiddenSysctls`: A list of explicitly denied sysctls. Any sysctl in this list will be considered forbidden. '*' and trailing wildcards are supported. If unspecified, no limitations are made by this parameter.

## Examples

```yaml
parameters:
allowedSysctls: ['*']
forbiddenSysctls:
- kernel.msg*
- net.core.somaxconn
```
```yaml
parameters:
allowedSysctls:
- kernel.shm_rmid_forced
- net.ipv4.ip_local_port_range
- net.ipv4.tcp_syncookies
- net.ipv4.ping_group_range
forbiddenSysctls: []
```
*Note*: `forbiddenSysctls` takes precedence, such that an explicitly forbidden sysctl is still forbidden even if it appears in `allowedSysctls` as well. However in practice, such overlap between the rules should be avoided.

## References

* [Using sysctls in a Kubernetes Cluster](https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/)
* [Kubernetes API Reference - Sysctl](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#sysctl-v1-core)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 1.2.0
name: k8spspforbiddensysctls
displayName: Forbidden Sysctls
createdAt: "2024-07-05T17:47:31Z"
description: Controls the `sysctl` profile used by containers. Corresponds to the `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden. The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter. For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/
digest: c34167b32bcd5b55b48a68614ad4b20cd26294d17be559738f01735ab719f621
license: Apache-2.0
homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/forbidden-sysctls
keywords:
- gatekeeper
- open-policy-agent
- policies
readme: |-
# Forbidden Sysctls
Controls the `sysctl` profile used by containers. Corresponds to the `allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy. When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden. The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter. For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/
install: |-
### Usage
```shell
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/forbidden-sysctls/1.2.0/template.yaml
```
provider:
name: Gatekeeper Library
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
resources:
- template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPForbiddenSysctls
metadata:
name: psp-forbidden-sysctls
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
forbiddenSysctls:
# - "*" # * may be used to forbid all sysctls
- kernel.*
allowedSysctls:
- "*" # allows all sysctls. allowedSysctls is optional.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPForbiddenSysctls
metadata:
name: psp-forbidden-sysctls
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
forbiddenSysctls:
- "*" # * forbid all sysctls
allowedSysctls:
- "*" # allows all sysctls. allowedSysctls is optional.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPForbiddenSysctls
metadata:
name: psp-forbidden-sysctls
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
forbiddenSysctls:
# - "*" # * may be used to forbid all sysctls
- kernel.*
allowedSysctls:
- "net.*" # allows all sysctls. allowedSysctls is optional.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-forbidden-sysctls-disallowed
labels:
app: nginx-forbidden-sysctls
spec:
containers:
- name: nginx
image: nginx
securityContext:
sysctls:
- name: net.core.somaxconn
value: "1024"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-forbidden-sysctls-disallowed
labels:
app: nginx-forbidden-sysctls
spec:
containers:
- name: nginx
image: nginx
securityContext:
sysctls:
- name: kernel.msgmax
value: "65536"
- name: net.core.somaxconn
value: "1024"
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
kind: AdmissionReview
apiVersion: admission.k8s.io/v1beta1
request:
operation: "UPDATE"
object:
apiVersion: v1
kind: Pod
metadata:
name: nginx-forbidden-sysctls-disallowed
labels:
app: nginx-forbidden-sysctls
spec:
containers:
- name: nginx
image: nginx
securityContext:
sysctls:
- name: kernel.msgmax
value: "65536"
- name: net.core.somaxconn
value: "1024"
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
kind: Suite
apiVersion: test.gatekeeper.sh/v1alpha1
metadata:
name: forbidden-sysctls
tests:
- name: forbidden-sysctls
template: template.yaml
constraint: samples/psp-forbidden-sysctls/constraint.yaml
cases:
- name: example-disallowed
object: samples/psp-forbidden-sysctls/example_disallowed.yaml
assertions:
- violations: yes
- name: example-allowed
object: samples/psp-forbidden-sysctls/example_allowed.yaml
assertions:
- violations: no
- name: update
object: samples/psp-forbidden-sysctls/update.yaml
assertions:
- violations: no
- name: forbidden-sysctls2
template: template.yaml
constraint: samples/psp-forbidden-sysctls/constraint2.yaml
cases:
- name: example-disallowed
object: samples/psp-forbidden-sysctls/example_disallowed.yaml
assertions:
- violations: yes
- name: example-allowed
object: samples/psp-forbidden-sysctls/example_allowed.yaml
assertions:
- violations: yes
- name: update
object: samples/psp-forbidden-sysctls/update.yaml
assertions:
- violations: no
- name: forbidden-sysctls3
template: template.yaml
constraint: samples/psp-forbidden-sysctls/constraint3.yaml
cases:
- name: example-disallowed
object: samples/psp-forbidden-sysctls/example_disallowed.yaml
assertions:
- violations: yes
- name: example-allowed
object: samples/psp-forbidden-sysctls/example_allowed.yaml
assertions:
- violations: no
- name: update
object: samples/psp-forbidden-sysctls/update.yaml
assertions:
- violations: no
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8spspforbiddensysctls
annotations:
metadata.gatekeeper.sh/title: "Forbidden Sysctls"
metadata.gatekeeper.sh/version: 1.2.0
description: >-
Controls the `sysctl` profile used by containers. Corresponds to the
`allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy.
When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden.
The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter.
For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/
spec:
crd:
spec:
names:
kind: K8sPSPForbiddenSysctls
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
description: >-
Controls the `sysctl` profile used by containers. Corresponds to the
`allowedUnsafeSysctls` and `forbiddenSysctls` fields in a PodSecurityPolicy.
When specified, any sysctl not in the `allowedSysctls` parameter is considered to be forbidden.
The `forbiddenSysctls` parameter takes precedence over the `allowedSysctls` parameter.
For more information, see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/
properties:
allowedSysctls:
type: array
description: "An allow-list of sysctls. `*` allows all sysctls not listed in the `forbiddenSysctls` parameter."
items:
type: string
forbiddenSysctls:
type: array
description: "A disallow-list of sysctls. `*` forbids all sysctls."
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
code:
- engine: K8sNativeValidation
source:
variables:
- name: sysctls
expression: '!has(variables.anyObject.spec.securityContext) ? [] : !has(variables.anyObject.spec.securityContext.sysctls) ? [] : variables.anyObject.spec.securityContext.sysctls'
- name: allowedSysctlPrefixes
expression: |
!has(variables.params.allowedSysctls) ? [] : variables.params.allowedSysctls.filter(sysctl, sysctl.endsWith("*")).map(sysctl, string(sysctl).replace("*", ""))
- name: allowedSysctlExplicit
expression: |
!has(variables.params.allowedSysctls) ? [] :
variables.params.allowedSysctls.filter(sysctl, !sysctl.endsWith("*"))
- name: forbiddenSysctlPrefixes
expression: |
!has(variables.params.forbiddenSysctls) ? [] : variables.params.forbiddenSysctls.filter(sysctl, sysctl.endsWith("*")).map(sysctl, string(sysctl).replace("*", ""))
- name: forbiddenSysctlExplicit
expression: |
!has(variables.params.forbiddenSysctls) ? [] :
variables.params.forbiddenSysctls.filter(sysctl, !sysctl.endsWith("*"))
- name: allAllowed
expression: '!has(variables.params.allowedSysctls) ? true : false'
- name: violatingSysctls
expression: |
(variables.sysctls.filter(sysctl,
(sysctl.name in variables.forbiddenSysctlExplicit ||
variables.forbiddenSysctlPrefixes.exists(fsp, string(sysctl.name).startsWith(fsp))) ||
(!variables.allAllowed &&
!(sysctl.name in variables.allowedSysctlExplicit) &&
!variables.allowedSysctlPrefixes.exists(asp, string(sysctl.name).startsWith(asp)))))
validations:
- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.violatingSysctls) == 0'
messageExpression: '"The sysctl is not allowed for pod: " + variables.anyObject.metadata.name + ", forbidden: " + variables.forbiddenSysctls.map(c, c).join(", ") + ", allowed: " + variables.allowedSysctls.map(c, c).join(", ")'
- engine: Rego
source:
rego: |
package k8spspforbiddensysctls
import data.lib.exclude_update.is_update
# Block if forbidden
violation[{"msg": msg, "details": {}}] {
# spec.securityContext.sysctls field is immutable.
not is_update(input.review)
sysctl := input.review.object.spec.securityContext.sysctls[_].name
forbidden_sysctl(sysctl)
msg := sprintf("The sysctl %v is not allowed, pod: %v. Forbidden sysctls: %v", [sysctl, input.review.object.metadata.name, input.parameters.forbiddenSysctls])
}
# Block if not explicitly allowed
violation[{"msg": msg, "details": {}}] {
not is_update(input.review)
sysctl := input.review.object.spec.securityContext.sysctls[_].name
not allowed_sysctl(sysctl)
msg := sprintf("The sysctl %v is not explicitly allowed, pod: %v. Allowed sysctls: %v", [sysctl, input.review.object.metadata.name, input.parameters.allowedSysctls])
}
# * may be used to forbid all sysctls
forbidden_sysctl(_) {
input.parameters.forbiddenSysctls[_] == "*"
}
forbidden_sysctl(sysctl) {
input.parameters.forbiddenSysctls[_] == sysctl
}
forbidden_sysctl(sysctl) {
forbidden := input.parameters.forbiddenSysctls[_]
endswith(forbidden, "*")
startswith(sysctl, trim_suffix(forbidden, "*"))
}
# * may be used to allow all sysctls
allowed_sysctl(_) {
input.parameters.allowedSysctls[_] == "*"
}
allowed_sysctl(sysctl) {
input.parameters.allowedSysctls[_] == sysctl
}
allowed_sysctl(sysctl) {
allowed := input.parameters.allowedSysctls[_]
endswith(allowed, "*")
startswith(sysctl, trim_suffix(allowed, "*"))
}
libs:
- |
package lib.exclude_update
is_update(review) {
review.operation == "UPDATE"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPForbiddenSysctls
metadata:
name: psp-forbidden-sysctls
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
forbiddenSysctls:
- "*" # * forbid all sysctls
allowedSysctls:
- "*" # allows all sysctls. allowedSysctls is optional.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPForbiddenSysctls
metadata:
name: psp-forbidden-sysctls
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
forbiddenSysctls:
# - "*" # * may be used to forbid all sysctls
- kernel.*
allowedSysctls:
- "net.*" # allows all sysctls. allowedSysctls is optional.
Loading

0 comments on commit 386428f

Please sign in to comment.