Skip to content

Commit

Permalink
fix: 1:1 mapping for rego:cel for psp-host-network-ports policy (#559)
Browse files Browse the repository at this point in the history
* fixing cel bugs for exemptImage

Signed-off-by: Jaydip Gabani <[email protected]>

* updating description

Signed-off-by: Jaydip Gabani <[email protected]>

* fixing test

Signed-off-by: Jaydip Gabani <[email protected]>

---------

Signed-off-by: Jaydip Gabani <[email protected]>
  • Loading branch information
JaydipGabani authored Jul 2, 2024
1 parent 799a307 commit 625ca8b
Show file tree
Hide file tree
Showing 16 changed files with 346 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 1.1.1
name: k8spsphostnetworkingports
displayName: Host Networking Ports
createdAt: "2024-06-25T22:51:27Z"
description: Controls usage of host network namespace by pod containers. Specific ports must be specified. Corresponds to the `hostNetwork` and `hostPorts` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces
digest: e97c59805103b9bcdeec7d92aace619039df7262feb78a91d5657240c3d2700a
license: Apache-2.0
homeURL: https://open-policy-agent.github.io/gatekeeper-library/website/host-network-ports
keywords:
- gatekeeper
- open-policy-agent
- policies
readme: |-
# Host Networking Ports
Controls usage of host network namespace by pod containers. Specific ports must be specified. Corresponds to the `hostNetwork` and `hostPorts` fields in a PodSecurityPolicy. For more information, see https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces
install: |-
### Usage
```shell
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/artifacthub/library/pod-security-policy/host-network-ports/1.1.1/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,13 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNetworkingPorts
metadata:
name: psp-host-network-ports
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
hostNetwork: true
min: 80
max: 9000
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostNetworkingPorts
metadata:
name: psp-host-network
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
hostNetwork: false
exemptImages:
- "nginx"
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-host-networking-ports-disallowed
labels:
app: nginx-host-networking-ports
spec:
hostNetwork: true
ephemeralContainers:
- name: nginx
image: nginx
ports:
- containerPort: 9001
hostPort: 9001
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-host-networking-ports-allowed
labels:
app: nginx-host-networking-ports
spec:
hostNetwork: false
containers:
- name: nginx
image: nginx
ports:
- containerPort: 9000
hostPort: 80
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx-host-networking-ports-disallowed
labels:
app: nginx-host-networking-ports
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx
ports:
- containerPort: 9001
hostPort: 9001
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
kind: AdmissionReview
apiVersion: admission.k8s.io/v1beta1
request:
operation: "UPDATE"
object:
apiVersion: v1
kind: Pod
metadata:
name: nginx-host-networking-ports-disallowed
labels:
app: nginx-host-networking-ports
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx
ports:
- containerPort: 9001
hostPort: 9001
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
kind: Suite
apiVersion: test.gatekeeper.sh/v1alpha1
metadata:
name: host-network-ports
tests:
- name: use-of-host-networking-ports-blocked
template: template.yaml
constraint: samples/psp-host-network-ports/constraint.yaml
cases:
- name: example-disallowed
object: samples/psp-host-network-ports/example_disallowed.yaml
assertions:
- violations: yes
- name: example-allowed
object: samples/psp-host-network-ports/example_allowed.yaml
assertions:
- violations: no
- name: disallowed-ephemeral
object: samples/psp-host-network-ports/disallowed_ephemeral.yaml
assertions:
- violations: yes
- name: update
object: samples/psp-host-network-ports/update.yaml
assertions:
- violations: no
- name: use-of-host-network-blocked
template: template.yaml
constraint: samples/psp-host-network-ports/constraint_block_host_network.yaml
cases:
- name: example-disallowed
object: samples/psp-host-network-ports/example_disallowed.yaml
assertions:
- violations: yes
- name: example-allowed
object: samples/psp-host-network-ports/example_allowed.yaml
assertions:
- violations: no
- name: disallowed-ephemeral
object: samples/psp-host-network-ports/disallowed_ephemeral.yaml
assertions:
- violations: yes
- name: update
object: samples/psp-host-network-ports/update.yaml
assertions:
- violations: no
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8spsphostnetworkingports
annotations:
metadata.gatekeeper.sh/title: "Host Networking Ports"
metadata.gatekeeper.sh/version: 1.1.1
description: >-
Controls usage of host network namespace by pod containers. HostNetwork verification happens without exception for exemptImages. Specific
ports must be specified. Corresponds to the `hostNetwork` and
`hostPorts` fields in a PodSecurityPolicy. For more information, see
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces
spec:
crd:
spec:
names:
kind: K8sPSPHostNetworkingPorts
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
description: >-
Controls usage of host network namespace by pod containers. HostNetwork verification happens without exception for exemptImages. Specific
ports must be specified. Corresponds to the `hostNetwork` and
`hostPorts` fields in a PodSecurityPolicy. For more information, see
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces
properties:
exemptImages:
description: >-
Any container that uses an image that matches an entry in this list will be excluded
from enforcement. Prefix-matching can be signified with `*`. For example: `my-image-*`.
It is recommended that users use the fully-qualified Docker image name (e.g. start with a domain name)
in order to avoid unexpectedly exempting images from an untrusted repository.
type: array
items:
type: string
hostNetwork:
description: "Determines if the policy allows the use of HostNetwork in the pod spec."
type: boolean
min:
description: "The start of the allowed port range, inclusive."
type: integer
max:
description: "The end of the allowed port range, inclusive."
type: integer
targets:
- target: admission.k8s.gatekeeper.sh
code:
- engine: K8sNativeValidation
source:
variables:
- name: containers
expression: 'has(variables.anyObject.spec.containers) ? variables.anyObject.spec.containers : []'
- name: initContainers
expression: 'has(variables.anyObject.spec.initContainers) ? variables.anyObject.spec.initContainers : []'
- name: ephemeralContainers
expression: 'has(variables.anyObject.spec.ephemeralContainers) ? variables.anyObject.spec.ephemeralContainers : []'
- name: exemptImagePrefixes
expression: |
!has(variables.params.exemptImages) ? [] :
variables.params.exemptImages.filter(image, image.endsWith("*")).map(image, string(image).replace("*", ""))
- name: exemptImageExplicit
expression: |
!has(variables.params.exemptImages) ? [] :
variables.params.exemptImages.filter(image, !image.endsWith("*"))
- name: exemptImages
expression: |
(variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container,
container.image in variables.exemptImageExplicit ||
variables.exemptImagePrefixes.exists(exemption, string(container.image).startsWith(exemption)))
- name: badContainers
expression: |
(variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container,
!(container.image in variables.exemptImages) &&
(
(container.ports.all(port, has(port.hostPort) && has(variables.params.min) && port.hostPort < variables.params.min)) ||
(container.ports.all(port, has(port.hostPort) && has(variables.params.max) && port.hostPort > variables.params.max))
)
)
validations:
- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.badContainers) == 0'
messageExpression: '"The specified hostNetwork and hostPort are not allowed, pod: " + variables.anyObject.metadata.name + ". Allowed values: " + variables.params'
- expression: |
(has(request.operation) && request.operation == "UPDATE") ||
(!has(variables.params.hostNetwork) || !variables.params.hostNetwork ? (has(variables.anyObject.spec.hostNetwork) && !variables.anyObject.spec.hostNetwork) : true)
messageExpression: '"The specified hostNetwork and hostPort are not allowed, pod: " + variables.anyObject.metadata.name + ". Allowed values: " + variables.params'
- engine: Rego
source:
rego: |
package k8spsphostnetworkingports
import data.lib.exclude_update.is_update
import data.lib.exempt_container.is_exempt
violation[{"msg": msg, "details": {}}] {
# spec.hostNetwork field is immutable.
not is_update(input.review)
input_share_hostnetwork(input.review.object)
msg := sprintf("The specified hostNetwork and hostPort are not allowed, pod: %v. Allowed values: %v", [input.review.object.metadata.name, input.parameters])
}
input_share_hostnetwork(o) {
not input.parameters.hostNetwork
o.spec.hostNetwork
}
input_share_hostnetwork(_) {
hostPort := input_containers[_].ports[_].hostPort
hostPort < input.parameters.min
}
input_share_hostnetwork(_) {
hostPort := input_containers[_].ports[_].hostPort
hostPort > input.parameters.max
}
input_containers[c] {
c := input.review.object.spec.containers[_]
not is_exempt(c)
}
input_containers[c] {
c := input.review.object.spec.initContainers[_]
not is_exempt(c)
}
input_containers[c] {
c := input.review.object.spec.ephemeralContainers[_]
not is_exempt(c)
}
libs:
- |
package lib.exclude_update
is_update(review) {
review.operation == "UPDATE"
}
- |
package lib.exempt_container
is_exempt(container) {
exempt_images := object.get(object.get(input, "parameters", {}), "exemptImages", [])
img := container.image
exemption := exempt_images[_]
_matches_exemption(img, exemption)
}
_matches_exemption(img, exemption) {
not endswith(exemption, "*")
exemption == img
}
_matches_exemption(img, exemption) {
endswith(exemption, "*")
prefix := trim_suffix(exemption, "*")
startswith(img, prefix)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ spec:
parameters:
hostNetwork: true
min: 80
max: 9000
max: 9000
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ spec:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
hostNetwork: false
hostNetwork: false
exemptImages:
- "nginx"
13 changes: 8 additions & 5 deletions library/pod-security-policy/host-network-ports/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ metadata:
name: k8spsphostnetworkingports
annotations:
metadata.gatekeeper.sh/title: "Host Networking Ports"
metadata.gatekeeper.sh/version: 1.1.0
metadata.gatekeeper.sh/version: 1.1.1
description: >-
Controls usage of host network namespace by pod containers. Specific
Controls usage of host network namespace by pod containers. HostNetwork verification happens without exception for exemptImages. Specific
ports must be specified. Corresponds to the `hostNetwork` and
`hostPorts` fields in a PodSecurityPolicy. For more information, see
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces
Expand All @@ -20,7 +20,7 @@ spec:
openAPIV3Schema:
type: object
description: >-
Controls usage of host network namespace by pod containers. Specific
Controls usage of host network namespace by pod containers. HostNetwork verification happens without exception for exemptImages. Specific
ports must be specified. Corresponds to the `hostNetwork` and
`hostPorts` fields in a PodSecurityPolicy. For more information, see
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#host-namespaces
Expand Down Expand Up @@ -74,14 +74,17 @@ spec:
(variables.containers + variables.initContainers + variables.ephemeralContainers).filter(container,
!(container.image in variables.exemptImages) &&
(
(!has(variables.params.hostNetwork) || !variables.params.hostNetwork ? (has(variables.anyObject.spec.hostNetwork) && variables.anyObject.spec.hostNetwork) : false) ||
(container.ports.all(port, has(port.hostPort) && has(variables.params.min) && port.hostPort < variables.params.min)) ||
(container.ports.all(port, has(port.hostPort) && has(variables.params.max) && port.hostPort > variables.params.max))
)
)
validations:
- expression: '(has(request.operation) && request.operation == "UPDATE") || size(variables.badContainers) == 0'
messageExpression: '"The specified hostNetwork and hostPort are not allowed, pod: " + variables.anyObject.metadata.name + ". Allowed values: " + variables.params'
messageExpression: '"The specified hostNetwork and hostPort are not allowed, pod: " + variables.anyObject.metadata.name + ". Allowed values: " + variables.params'
- expression: |
(has(request.operation) && request.operation == "UPDATE") ||
(!has(variables.params.hostNetwork) || !variables.params.hostNetwork ? (has(variables.anyObject.spec.hostNetwork) && !variables.anyObject.spec.hostNetwork) : true)
messageExpression: '"The specified hostNetwork and hostPort are not allowed, pod: " + variables.anyObject.metadata.name + ". Allowed values: " + variables.params'
- engine: Rego
source:
rego: |
Expand Down
Loading

0 comments on commit 625ca8b

Please sign in to comment.