Linting Kubernetes Deployments using config-lint

DevOps is all about automation and security. One of the biggest attractions to using Kubernetes is the ability to automate cluster and resource creation. However, how do you ensure that all the resources follow specific guidelines without one or two resources slipping through the cracks? That’s where config-lint comes in. It’s a command line tool used to validate Kubernetes, Terraform, and JSON files that is available on GitHub.

It can be an invaluable tool that can be integrated in your CI/CD Pipeline to lint your Kubernetes resources before deployment.

The command to check rules using config-lint rule is:

config-lint -rules <rule-file-name.yml> --exclude-from <exclude-list-file> <directory to lint> 

Below is a snippet of a YAML rule file:

version: 1
description: Rules for Kubernetes spec files
type: Kubernetes
files:
  - "*.yml"
rules:

  - id: ALLOW_KIND
    severity: FAILURE
    message: Allowed kinds
    resource: "*"
    assertions:
      - key: kind
        op: in
        value: Pod,Policy,ServiceAccount,NetworkPolicy
    tags:
      - kind

  - id: POD_CONTAINERS
    severity: FAILURE
    message: Pod must include containers
    resource: Pod
    assertions:
      - key: spec.containers
        op: present
    tags:
      - pod

  - id: POD_SECURITY_CONTEXT
    severity: FAILURE
    message: Pod should set securityContent
    resource: Pod
    assertions:
      - key: spec.securityContext.runAsNonRoot
        op: eq
        value: true
      - key: spec.securityContext.readOnlyRootFilesystem
        op: eq
        value: true
    tags:
      - pod
      - security

  - id: DEFAULT_NAMESPACE
    severity: FAILURE
    message: Policy should not use default namespace
    resource: Policy
    assertions:
      - key: spec.namespace
        op: ne
        value: default
    tags:
      - policy

  - id: NETWORK
    severity: FAILURE
    message: Network policy should include from pods
    resource: NetworkPolicy
    assertions:
      - key: spec.allowIncoming.from[].pods
        op: present
    tags:
      - network
  - id: DOCKER_REGISTRY
    severity: FAILURE
    message: Pods should pull from one of these docker registries
    resource: Pod
    assertions:
     - every:
         key: spec.containers
         expressions:
           - or:
             - key: image
               op: starts-with
               value: <private docker registry url 1>
             - key: image
               op: starts-with
               value: <private docker registry url 2>
    tags:
      - pod

Below is an example of a rule failure:

[
  {
    "AssertionMessage": "Or expression fails: spec.containers does not start with <private docker registry url 1>",
    "Category": "",
    "CreatedAt": "2019-02-27T23:10:09Z",
    "Filename": "k8s_config.yml",
    "LineNumber": 0,
    "ResourceID": "example-resource",
    "ResourceType": "Role",
    "RuleID": "DOCKER_REGISTRY",
    "RuleMessage": "Pods should pull from one of these docker registries",
    "Status": "FAILURE"
  }
]

The great thing about config-lint is that it can be used to lint other configuration files such as Terraform (.tf), JSON, YAML, and other file formats.

*Cover Images from kubernetes.io