Linting is the process of running validations on descriptors.

Bundlebee is able to read common "pre-rendered" descriptors (from Helm for example) as long as a manifest.json is properly formatted so you can run the linter on any descriptor even if it is working out of the box for Bundlebee alveoli (where you just run bundlebee lint …​ command without pre-processing).

Configure

The main configuration of the linter are the inclusions or exclusions (see lint command details).

You can also exclude rules in ignoredLintingRules of the manifest.json (per manifest not global) or in the descriptors directly using virtual $bundlebeeIgnoredLintingRules attribute which is equivalent.

Tip
while in the manifest the list is a list of object with a name attribute, manifest and descriptor lists are list of rule names to keep it simple.

Indeed the lint command enables to exclude alveoli and descriptors but it is generally more convenient to create a my-project:lint alveolus which will disable (using placeholders or includeIf conditions) undesired external dependencies and descriptors during the linting process. This makes it quite easy and efficient to control what you deploy and avoid to trigger rules you don’t want.

Rules

Here is the available rules (built-in).

Linting Checks

Here is the list of available checks by defaults.

access-to-create-pods

Name: access-to-create-pods.

Indicates when a subject (Group/User/ServiceAccount) has create access to Pods. CIS Benchmark 5.1.4: The ability to create pods in a cluster opens up possibilities for privilege escalation and should be restricted, where possible.

Remediation

Where possible, remove create access to pod objects in the cluster.

access-to-secrets

Name: access-to-secrets.

Indicates when a subject (Group/User/ServiceAccount) has access to Secrets. CIS Benchmark 5.1.2: Access to secrets should be restricted to the smallest possible group of users to reduce the risk of privilege escalation.

Remediation

Where possible, remove get, list and watch access to secret objects in the cluster.

cpu-limits

Name: cpu-limits.

Ensures resources.limits.cpu is set.

Remediation

Set resources.limits.cpu.

cpu-requests

Name: cpu-requests.

Ensures resources.requests.cpu is set.

Remediation

Set resources.requests.cpu.

default-service-account

Name: default-service-account.

Indicates when pods use the default service account.

Remediation

Create a dedicated service account for your pod. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ for details.

deprecated-service-account-field

Name: deprecated-service-account-field.

Indicates when deployments use the deprecated serviceAccount field.

Remediation

Use the serviceAccountName field instead. If you must specify serviceAccount, ensure values for serviceAccount and serviceAccountName match.

dnsconfig-options

Name: dnsconfig-options.

Alert on deployments that have no specified dnsConfig options

Remediation

Specify dnsconfig options in your Pod specification to ensure the expected DNS setting on the Pod. Refer to https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config for details.

docker-sock

Name: docker-sock.

Alert on deployments with docker.sock mounted in containers.

Remediation

Ensure the Docker socket is not mounted inside any containers by removing the associated Volume and VolumeMount in deployment yaml specification. If the Docker socket is mounted inside a container it could allow processes running within the container to execute Docker commands which would effectively allow for full control of the host.

drop-net-raw-capability

Name: drop-net-raw-capability.

Indicates when containers do not drop NET_RAW capability

Remediation

NET_RAW makes it so that an application within the container is able to craft raw packets, use raw sockets, and bind to any address. Remove this capability in the containers under containers security contexts.

duplicate-env-var

Name: duplicate-env-var.

Check that duplicate named env vars aren’t passed to a deployment like.

Remediation

Confirm that your DeploymentLike doesn’t have duplicate env vars names.

host-ipc

Name: host-ipc.

Alert on pods/deployment-likes with sharing host’s IPC namespace

Remediation

Ensure the host’s IPC namespace is not shared.

host-network

Name: host-network.

Alert on pods/deployment-likes with sharing host’s network namespace

Remediation

Ensure the host’s network namespace is not shared.

host-pid

Name: host-pid.

Alert on pods/deployment-likes with sharing host’s process namespace

Remediation

Ensure the host’s process namespace is not shared.

hpa-minimum-three-replicas

Name: hpa-minimum-three-replicas.

Indicates when a HorizontalPodAutoscaler specifies less than three minReplicas

Remediation

Increase the number of replicas in the HorizontalPodAutoscaler to at least three to increase fault tolerance.

memory-limits

Name: memory-limits.

Ensures resources.limits.memory is set.

Remediation

Set resources.limits.memory.

memory-requests

Name: memory-requests.

Ensures resources.requests.memory is set.

Remediation

Set resources.requests.memory.

minimum-three-replicas

Name: minimum-three-replicas.

Indicates when a deployment uses less than three replicas

Remediation

Increase the number of replicas in the deployment to at least three to increase the fault tolerance of the deployment.

mismatching-selector

Name: mismatching-selector.

Indicates when deployment selectors fail to match the pod template labels.

Remediation

Confirm that your deployment selector correctly matches the labels in its pod template.

missing-anti-affinity

Name: missing-anti-affinity.

When replicas > 1 setting an anti-affinity enables to distribute the load accross machines setting 'topologyKey: "kubernetes.io/hostname"', see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity.

Remediation

Add podAntiAffinity in your deployment descriptor.

no-extensions-v1beta

Name: no-extensions-v1beta.

Indicates when objects use deprecated API versions under extensions/v1beta.

Remediation

Migrate using the apps/v1 API versions for the objects. Refer to https://kubernetes.io/blog/2019/07/18/api-deprecations-in-1-16/ for details.

no-latest

Name: no-latest.

Ensures no latest image is used.

Remediation

Ensure to tag any image you use and use an immutable tag if possible or at least versionned flavor.

no-liveness-probe

Name: no-liveness-probe.

Ensures a liveness probe is defined.

Remediation

Any container (from containers array) should have a liveness probe.

no-read-only-root-fs

Name: no-read-only-root-fs.

Indicates when containers are running without a read-only root filesystem.

Remediation

Set readOnlyRootFilesystem to true in the container securityContext.

no-readiness-probe

Name: no-readiness-probe.

Ensures a readinessProbe probe is defined.

Remediation

Any container (from containers array) should have a readinessProbe probe.

privilege-escalation-container

Name: privilege-escalation-container.

Alert on containers of allowing privilege escalation that could gain more privileges than its parent process.

Remediation

Ensure containers do not allow privilege escalation by setting allowPrivilegeEscalation=false, privileged=false and removing CAP_SYS_ADMIN capability. See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for more details.

privileged-container

Name: privileged-container.

Indicates when deployments have containers running in privileged mode.

Remediation

Do not run your container as privileged unless it is required.

privileged-ports

Name: privileged-ports.

Alert on deployments with privileged ports mapped in containers

Remediation

Ensure privileged ports [0, 1024] are not mapped within containers.

read-secret-from-env-var

Name: read-secret-from-env-var.

Indicates when a deployment reads secret from environment variables. CIS Benchmark 5.4.1: "Prefer using secrets as files over secrets as environment variables. "

Remediation

If possible, rewrite application code to read secrets from mounted secret files, rather than from environment variables. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets for details.

run-as-non-root

Name: run-as-non-root.

Indicates when containers are not set to runAsNonRoot.

Remediation

Set runAsUser to a non-zero number and runAsNonRoot to true in your pod or container securityContext. Refer to https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ for details.

sensitive-host-mounts

Name: sensitive-host-mounts.

Alert on deployments with sensitive host system directories mounted in containers.

Remediation

Ensure sensitive host system directories are not mounted in containers by removing those Volumes and VolumeMounts.

unsafe-proc-mount

Name: unsafe-proc-mount.

Alert on deployments with unsafe /proc mount (procMount=Unmasked) that will bypass the default masking behavior of the container runtime

Remediation

Ensure container does not unsafely exposes parts of /proc by setting procMount=Default. Unmasked ProcMount bypasses the default masking behavior of the container runtime. See https://kubernetes.io/docs/concepts/security/pod-security-standards/ for more details.

unsafe-sysctls

Name: unsafe-sysctls.

Alert on deployments specifying unsafe sysctls that may lead to severe problems like wrong behavior of containers

Remediation

Ensure container does not allow unsafe allocation of system resources by removing unsafe sysctls configurations. For more details see https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster/ https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime.

use-namespace

Name: use-namespace.

Indicates when a resource is deployed to the default namespace. CIS Benchmark 5.7.1: Create administrative boundaries between resources using namespaces. CIS Benchmark 5.7.4: The default namespace should not be used.

Remediation

Create namespaces for objects in your deployment.

wildcard-in-rules

Name: wildcard-in-rules.

Indicate when a wildcard is used in Role or ClusterRole rules. CIS Benchmark 5.1.3 Use of wildcards is not optimal from a security perspective as it may allow for inadvertent access to be granted when new resources are added to the Kubernetes API either as CRDs or in later versions of the product.

Remediation

Where possible replace any use of wildcards in clusterroles and roles with specific objects or actions.

writable-host-mount

Name: writable-host-mount.

Indicates when containers mount a host path as writable.

Remediation

Set containers to mount host paths as readOnly, if you need to access files on the host.

Write your own rule

To write your own rule you have to implement and add to bundlebee (core) classpath a CDI bean implementing LintingCheck - or SynchronousLintingCheck which can be easier to implement.

Synchronous or not

The generic LintingCheck uses CompletionStage because it is possible to use validation rules which connect to a cluster (the bundlebee configured one) and using KubeClient - or any other logic - you can do checks against a particular cluster (does role exists for example). CompletionStage enable to run validations in parallel easily.

When not needed, just go with the SynchronousLintingCheck base interface or one of its children.

Anatomy of a check

A check is composed of:

  • A name which enables to disable/force the check to run,

  • A remediation string which explains how to fix the violation when it happens,

  • A decription explaining the validation,

  • A validate (or sync flavor) method doing validation when a descriptor is visited,

  • Sometimes an afterAll method doing validations after all descriptors were seen (for joins accross desriptors for example).

JSON, JSON, JSON

Yaml descriptors are converted to JsonObject and descriptors containing a list are flattened.

What does it means is that you always validate a single descriptor which is an object in check code which makes it easier to work with.

Going further

It is not yet possible to define custom rules, it is not very complicated to do it technically but the language (must be JSON based) is challenging. Here are the current evaluated options:

  • Custom DSL: likely the most powerful and consistent option since we could define it in manifest.json but requires to learn yet another language,

  • JSON-Logic: a very good option but requires a lot of operators and resulting DSL is not that friendly/simple,

  • Template based: idea there is to define a few options ("check this value at this JSON pointer", "check this chain of json pointer", …​) but this becomes quite hard to have a relevant dictionary set without making it overcomplex,

  • Scripting based: we can run jruby/jython/js engine rules but they all required to embed a script manager runtime and they tend to be fatty for this need and not all are graalvm friendly to convert bundlebee to native mode.

So as of today, since we didn’t find a compromise making us happy we didn’t enable to define JSON DSL based rules. Since it is easy to add custom rules in Java (and using the maven plugin), this is not blocking but we’d like to tackle it if we can come up with a better idea. Don’t hesistate to propose something on bundlebee github project if you have an idea or a common need.