checkov icon indicating copy to clipboard operation
checkov copied to clipboard

Support missing resource checks

Open mariyan22 opened this issue 1 year ago • 6 comments

Hello Team,

I've created a custom check that searches for PodDisruptionBudget resources and verifies if the minAvailable option is not lower than 1 replica. The check works fine when there is a PodDisruptionBudget kind in our repo, but it gets skipped by checkov when there is no PodDisruptionBudget present. The expected behaviour is that the check should fail when it doesn't find a PDB.

This is the sample code -

` from typing import Any, Dict from checkov.common.models.enums import CheckResult, CheckCategories from checkov.kubernetes.checks.resource.base_spec_check import BaseK8Check

MIN_PODS_COUNT = 1

class PodDisruptionBudgetMinAvailableCheck(BaseK8Check):

def __init__(self):
    name = "Ensure PodDisruptionBudget minAvailable is at least 1"
    id = "CKV_K8S_CUSTOM_4"
    categories = [CheckCategories.KUBERNETES]
    supported_kind = ["PodDisruptionBudget"]
    super().__init__(name=name, id=id, categories=categories, supported_entities=supported_kind)

def check(self, conf: Dict[str, Any]) -> CheckResult:
    has_pdb = False
    for kind in self.supported_entities:
        if kind.lower() in conf["kind"].lower():
            has_pdb = True
            break
    if not has_pdb:
        return CheckResult.FAILED

    return super().check(conf)

def scan_spec_conf(self, conf: Dict[str, Any]) -> CheckResult:
    if not self.contains_pdb(conf):
        return CheckResult.FAILED

    spec = conf.get("spec", {})
    min_available = spec.get("minAvailable", None)
    if min_available is not None and min_available >= MIN_PODS_COUNT:
        return CheckResult.PASSED
    return CheckResult.FAILED

def contains_pdb(self, conf: Dict[str, Any]) -> bool:
    api_version = conf.get("apiVersion", "")
    kind = conf.get("kind", "")

    return api_version.startswith("policy") and kind == "PodDisruptionBudget"

check = PodDisruptionBudgetMinAvailableCheck()`

I'm running this in Gitlab CI with checkov image 2.3.88. I'm adding both --run-all-external-checks and --external-checks-dir flags. Can you please advise, how can I run this check even when there is no PDB resource in the repo?

mariyan22 avatar Apr 18 '23 17:04 mariyan22

hey @mariyan22 thanks for reaching out.

There is currently no way to do it with checkov.

gruebel avatar Apr 19 '23 09:04 gruebel

@gruebel for the PDB-specific case, would it be possible to enable this by using cond_type: connector and ensuring that every pod/deployment/etc is connected to a PDB?

cryptaliagy avatar Aug 17 '23 05:08 cryptaliagy

@gruebel do you have any more resources on using the cond_type: connector? I'd love to take a crack at this but I haven't found a lot of information on that type

cryptaliagy avatar Sep 08 '23 15:09 cryptaliagy

Thanks for contributing to Checkov! We've automatically marked this issue as stale to keep our issues list tidy, because it has not had any activity for 6 months. It will be closed in 14 days if no further activity occurs. Commenting on this issue will remove the stale tag. If you want to talk through the issue or help us understand the priority and context, feel free to add a comment or join us in the Checkov slack channel at codifiedsecurity.slack.com Thanks!

stale[bot] avatar Mar 12 '24 11:03 stale[bot]

Any project maintainers able to offer any additional context?

cryptaliagy avatar Mar 18 '24 16:03 cryptaliagy

Hi @mariyan22 and @cryptaliagy, for this check, I believe you'll need a graph check to check that the resource is attached to a PodDisruptionBudget and that the PodDisruptionBudget has a minAvailable greater than 0. Based on the docs, the relevant resources are Deployment, ReplicationController, ReplicaSet, and StatefulSet. So the policy would look like this:

definition:
  and:
    - cond_type: filter
      attribute: resource_type
      value:
        - Deployment
        - ReplicationController
        - ReplicaSet
        - StatefulSet
      operator: within
    - resource_types:
        - Deployment
        - ReplicationController
        - ReplicaSet
        - StatefulSet
      connected_resource_types:
        - PodDisruptionBudget
      operator: exists
      cond_type: connection
    - cond_type: "attribute"
      resource_types:
        - "PodDisruptionBudget"
      attribute: "spec.minAvailable"
      operator: "exists"
    - cond_type: "attribute"
      resource_types:
        - "PodDisruptionBudget"
      attribute: "spec.minAvailable"
      operator: "greater_than"
      value: "0"

If that works, it's a good policy and please contribute it with some tests!

tsmithv11 avatar Jul 12 '24 17:07 tsmithv11