diff --git a/checkov/terraform/checks/resource/azure/AKSOnlyCriticalPodsOnSystemNodes.py b/checkov/terraform/checks/resource/azure/AKSOnlyCriticalPodsOnSystemNodes.py new file mode 100644 index 00000000000..04e1724e547 --- /dev/null +++ b/checkov/terraform/checks/resource/azure/AKSOnlyCriticalPodsOnSystemNodes.py @@ -0,0 +1,24 @@ +from checkov.common.models.enums import CheckCategories +from checkov.terraform.checks.resource.base_resource_value_check import BaseResourceValueCheck +from typing import Any + + +class AKSOnlyCriticalPodsOnSystemNodes(BaseResourceValueCheck): + def __init__(self) -> None: + """ + Microsoft recommends to isolate critical system pods from application pods + to prevent misconfigured or rogue application pods from accidentally killing system pods. + + This can be enforced by creating a dedicated system node pool with the CriticalAddonsOnly=true:NoSchedule taint + to prevent application pods from being scheduled on system node pools. + """ + name = "Ensure that only critical system pods run on system nodes" + id = "CKV_AZURE_229" + supported_resources = ("azurerm_kubernetes_cluster",) + categories = (CheckCategories.KUBERNETES,) + super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources) + + def get_inspected_key(self) -> str: + return "default_node_pool/[0]/only_critical_addons_enabled" + +check = AKSOnlyCriticalPodsOnSystemNodes() \ No newline at end of file diff --git a/tests/terraform/checks/resource/azure/example_AKSOnlyCriticalPodsOnSystemNodes/main.tf b/tests/terraform/checks/resource/azure/example_AKSOnlyCriticalPodsOnSystemNodes/main.tf new file mode 100644 index 00000000000..e884148f1bb --- /dev/null +++ b/tests/terraform/checks/resource/azure/example_AKSOnlyCriticalPodsOnSystemNodes/main.tf @@ -0,0 +1,34 @@ +resource "azurerm_kubernetes_cluster" "pass" { + name = "example" + + default_node_pool { + name = "defaultpool" + only_critical_addons_enabled = true +} + +resource "azurerm_kubernetes_cluster" "fail1" { + name = "example" + + default_node_pool { + name = "defaultpool" +} + +resource "azurerm_kubernetes_cluster" "fail2" { + name = "example" + + default_node_pool { + name = "defaultpool" + only_critical_addons_enabled = false +} + +resource "azurerm_kubernetes_cluster" "fail3" { + name = "example" + +} + +resource "azurerm_kubernetes_cluster" "fail4" { + name = "example" + only_critical_addons_enabled = true + +} + diff --git a/tests/terraform/checks/resource/azure/test_AKSOnlyCriticalPodsOnSystemNodes.py b/tests/terraform/checks/resource/azure/test_AKSOnlyCriticalPodsOnSystemNodes.py new file mode 100644 index 00000000000..8b311f4d20a --- /dev/null +++ b/tests/terraform/checks/resource/azure/test_AKSOnlyCriticalPodsOnSystemNodes.py @@ -0,0 +1,43 @@ +import os +import unittest + +from checkov.runner_filter import RunnerFilter +from checkov.terraform.runner import Runner +from checkov.terraform.checks.resource.azure.AKSOnlyCriticalPodsOnSystemNodes import check + + +class TestAKSOnlyCriticalPodsOnSystemNodes(unittest.TestCase): + def test(self): + runner = Runner() + current_dir = os.path.dirname(os.path.realpath(__file__)) + + test_files_dir = os.path.join(current_dir, "example_AKSOnlyCriticalPodsOnSystemNodes") + report = runner.run(root_folder=test_files_dir, + runner_filter=RunnerFilter(checks=[check.id])) + summary = report.get_summary() + + passing_resources = { + 'azurerm_kubernetes_cluster.pass', + } + failing_resources = { + 'azurerm_kubernetes_cluster.fail1', + 'azurerm_kubernetes_cluster.fail2', + 'azurerm_kubernetes_cluster.fail3', + 'azurerm_kubernetes_cluster.fail4', + } + skipped_resources = {} + + passed_check_resources = {c.resource for c in report.passed_checks} + failed_check_resources = {c.resource for c in report.failed_checks} + + self.assertEqual(summary['passed'], len(passing_resources)) + self.assertEqual(summary['failed'], len(failing_resources)) + self.assertEqual(summary['skipped'], len(skipped_resources)) + self.assertEqual(summary['parsing_errors'], 0) + + self.assertEqual(passing_resources, passed_check_resources) + self.assertEqual(failing_resources, failed_check_resources) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file