Skip to content

Commit

Permalink
Added utils methods for checking deployment and deploymentconfig (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
garethahealy authored Jun 25, 2020
1 parent 860229d commit 4272392
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 112 deletions.
5 changes: 5 additions & 0 deletions policy/utils/kubernetes.rego
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ isList {
isNotList {
not isList
}

isDeployment {
input.apiVersion == "apps/v1"
input.kind == "Deployment"
}
15 changes: 15 additions & 0 deletions policy/utils/openshift.rego
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package utils.openshift

import data.utils.kubernetes

isTemplate {
input.apiVersion == "template.openshift.io/v1"
input.kind == "Template"
Expand All @@ -8,3 +10,16 @@ isTemplate {
isNotTemplate {
not isTemplate
}

isDeploymentConfig {
input.apiVersion == "apps.openshift.io/v1"
input.kind == "DeploymentConfig"
}

isDeploymentOrDeploymentConfig {
isDeploymentConfig
}

isDeploymentOrDeploymentConfig {
kubernetes.isDeployment
}
140 changes: 30 additions & 110 deletions policy/warn-k8s_ocp-deployment_deploymentconfig-bestpractices.rego
Original file line number Diff line number Diff line change
@@ -1,68 +1,52 @@
package main

import data.utils.openshift

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
not input.spec.replicas

msg := sprintf("%s/%s: replicas is null.", [input.kind, input.metadata.name])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
input.spec.replicas <= 1

msg := sprintf("%s/%s: replicas is %d - expected replicas to be greater than 1 for HA guarantees.", [input.kind, input.metadata.name, input.spec.replicas])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
input.spec.replicas % 2 == 0

msg := sprintf("%s/%s: replicas is %d - expected an odd number for HA guarantees.", [input.kind, input.metadata.name, input.spec.replicas])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
not container.readinessProbe

msg := sprintf("%s/%s: container '%s' has no readinessProbe. See: https://docs.openshift.com/container-platform/4.4/applications/application-health.html", [input.kind, input.metadata.name, container.name])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
not container.livenessProbe

msg := sprintf("%s/%s: container '%s' has no livenessProbe. See: https://docs.openshift.com/container-platform/4.4/applications/application-health.html", [input.kind, input.metadata.name, container.name])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
container.livenessProbe
container.readinessProbe
Expand All @@ -72,14 +56,11 @@ warn[msg] {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]

# "Factor out" is_limits_or_requests_set to do an OR
# "Factor out" isLimitsOrRequestsSet to do an OR
not isLimitsOrRequestsSet with input as container

msg := sprintf("%s/%s: container '%s' has no limits/request for its resources. See: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers", [input.kind, input.metadata.name, container.name])
Expand All @@ -94,23 +75,17 @@ isLimitsOrRequestsSet {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
not container.resources.limits.memory

msg := sprintf("%s/%s: container '%s' has no memory limits. It is recommended to limit memory, as memory always has a maximum. See: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers", [input.kind, input.metadata.name, container.name])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]

not isResourceMemoryUnitsValid with input as container
Expand All @@ -128,11 +103,8 @@ isResourceMemoryUnitsValid {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]

not isResourceCpuRequestsUnitsValid with input as container
Expand Down Expand Up @@ -160,11 +132,8 @@ isResourceCpuRequestsUnitsValid {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]

isResourceMemoryInverted with input as container
Expand All @@ -180,46 +149,34 @@ isResourceMemoryInverted {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
container.resources.limits.cpu

msg := sprintf("%s/%s: container '%s' has cpu limits (%d). It is not recommended to limit cpu. See: https://www.reddit.com/r/kubernetes/comments/all1vg/on_kubernetes_cpu_limits", [input.kind, input.metadata.name, container.name, container.resources.limits.cpu])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
endswith(container.image, ":latest")

msg := sprintf("%s/%s: container '%s' is using the latest tag for its image (%s), which is an anti-pattern.", [input.kind, input.metadata.name, container.name, container.image])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
input.spec.template.spec.hostNetwork

msg := sprintf("%s/%s: hostNetwork is present which gives the pod access to the loopback device, services listening on localhost, and could be used to snoop on network activity of other pods on the same node.", [input.kind, input.metadata.name])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
volume := input.spec.template.spec.volumes[_]
not containersVolumeMountsContainsVolume(input.spec.template.spec.containers, volume)

Expand All @@ -231,11 +188,8 @@ containersVolumeMountsContainsVolume(containers, volume) {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
volumeMount := container.volumeMounts[_]
not volumesContainsVolumeMount(input.spec.template.spec.volumes, volumeMount)
Expand All @@ -248,11 +202,8 @@ volumesContainsVolumeMount(volumes, volumeMount) {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
volumeMount := container.volumeMounts[_]
not startswith(volumeMount.mountPath, "/var/run")
Expand All @@ -261,11 +212,8 @@ warn[msg] {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
env := container.env[_]
env.valueFrom.secretKeyRef
Expand All @@ -274,11 +222,8 @@ warn[msg] {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
env := container.env[_]
env.valueFrom.secretKeyRef
Expand All @@ -287,11 +232,8 @@ warn[msg] {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
isCommonK8sLabelNotSet with input as input.spec.template.metadata

msg := sprintf("%s/%s: does not contain all the expected k8s labels in 'spec.template.metadata.labels'. See: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels", [input.kind, input.metadata.name])
Expand All @@ -318,11 +260,8 @@ isCommonK8sLabelNotSet {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
not isEnvMaxMemorySet with input as container

Expand All @@ -336,11 +275,7 @@ isEnvMaxMemorySet {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]

input.apiVersion == apis[_]
input.kind == kinds[_]
openshift.isDeploymentOrDeploymentConfig

some key
value := input.metadata.labels[key]
Expand All @@ -359,35 +294,26 @@ labelKeyStartsWithExpected(key) {
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
not is_array(container.command)

msg := sprintf("%s/%s: container '%s' command '%s' is not an array. See: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container", [input.kind, input.metadata.name, container.name, container.command])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
not is_array(container.args)

msg := sprintf("%s/%s: container '%s' args '%s' is not an array. See: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container", [input.kind, input.metadata.name, container.name, container.args])
}

warn[msg] {
apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
containerOptsContainsXmx with input as container

Expand All @@ -412,16 +338,13 @@ containerOptsContainsXmx {
warn[msg] {
#NOTE: upperBound is an arbitrary number and it should be changed to what your company believes is the correct policy

apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

kb := 1024
mb := kb * 1024
gb := mb * 1024
upperBound := 6 * gb

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
memoryInBytes := units.parse_bytes(container.resources.limits.memory)
memoryInBytes > upperBound
Expand All @@ -432,16 +355,13 @@ warn[msg] {
warn[msg] {
#NOTE: upperBound is an arbitrary number and it should be changed to what your company believes is the correct policy

apis := ["apps/v1", "apps.openshift.io/v1"]
kinds := ["Deployment", "DeploymentConfig"]
openshift.isDeploymentOrDeploymentConfig

kb := 1024
mb := kb * 1024
gb := mb * 1024
upperBound := 2 * gb

input.apiVersion == apis[_]
input.kind == kinds[_]
container := input.spec.template.spec.containers[_]
memoryInBytes := units.parse_bytes(container.resources.requests.memory)
memoryInBytes > upperBound
Expand Down
Loading

0 comments on commit 4272392

Please sign in to comment.