Skip to content

Commit

Permalink
feat(terraform): add public network checks for Azure Function and Web…
Browse files Browse the repository at this point in the history
… Apps (#5533)

* add public network checks for Azure Function and Web Apps

* fix tests
  • Loading branch information
gruebel committed Sep 7, 2023
1 parent fa34d2b commit 6b04f95
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Any

from checkov.common.models.enums import CheckCategories
from checkov.terraform.checks.resource.base_resource_value_check import BaseResourceValueCheck


class AppServicePublicAccessDisabled(BaseResourceValueCheck):
def __init__(self) -> None:
name = "Ensure that Azure Web App public network access is disabled"
id = "CKV_AZURE_222"
supported_resources = ("azurerm_linux_web_app", "azurerm_windows_web_app")
categories = (CheckCategories.NETWORKING,)
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def get_inspected_key(self) -> str:
return "public_network_access_enabled"

def get_expected_value(self) -> Any:
return False


check = AppServicePublicAccessDisabled()
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class DataLakeStoreEncryption(BaseResourceValueCheck):
def __init__(self):
name = "Ensure that Data Lake Store accounts enables encryption"
id = "CKV_AZURE_105"
supported_resources = ['azurerm_data_lake_store']
categories = [CheckCategories.IAM]
supported_resources = ('azurerm_data_lake_store',)
categories = (CheckCategories.ENCRYPTION,)
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources, missing_block_result=CheckResult.PASSED)

def get_inspected_key(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from typing import Any

from checkov.common.models.enums import CheckCategories
from checkov.terraform.checks.resource.base_resource_value_check import BaseResourceValueCheck


class FunctionAppPublicAccessDisabled(BaseResourceValueCheck):
def __init__(self) -> None:
name = "Ensure that Azure Function App public network access is disabled"
id = "CKV_AZURE_221"
supported_resources = (
"azurerm_linux_function_app",
"azurerm_linux_function_app_slot",
"azurerm_windows_function_app",
"azurerm_windows_function_app_slot",
)
categories = (CheckCategories.NETWORKING,)
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def get_inspected_key(self) -> str:
return "public_network_access_enabled"

def get_expected_value(self) -> Any:
return False


check = FunctionAppPublicAccessDisabled()
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class RedisCachePublicNetworkAccessEnabled(BaseResourceValueCheck):
def __init__(self):
name = "Ensure that Azure Cache for Redis disables public network access"
id = "CKV_AZURE_89"
supported_resources = ['azurerm_redis_cache']
categories = [CheckCategories.IAM]
supported_resources = ('azurerm_redis_cache',)
categories = (CheckCategories.NETWORKING,)
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def get_inspected_key(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# pass

resource "azurerm_linux_web_app" "disabled" {
name = "example"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_service_plan.example.location
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = false
}

resource "azurerm_windows_web_app" "disabled" {
name = "example"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_service_plan.example.location
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = false
}

# fail

resource "azurerm_linux_web_app" "default" {
name = "example"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_service_plan.example.location
service_plan_id = azurerm_service_plan.example.id
}

resource "azurerm_windows_web_app" "default" {
name = "example"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_service_plan.example.location
service_plan_id = azurerm_service_plan.example.id
}

resource "azurerm_linux_web_app" "enabled" {
name = "example"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_service_plan.example.location
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = true
}

resource "azurerm_windows_web_app" "enabled" {
name = "example"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_service_plan.example.location
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# pass

resource "azurerm_linux_function_app" "disabled" {
name = "example-linux-function-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_account_name = azurerm_storage_account.example.name
storage_account_access_key = azurerm_storage_account.example.primary_access_key
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = false
}

resource "azurerm_linux_function_app_slot" "disabled" {
name = "example-linux-function-app-slot"
function_app_id = azurerm_linux_function_app.example.id
storage_account_name = azurerm_storage_account.example.name

public_network_access_enabled = false
}

resource "azurerm_windows_function_app" "disabled" {
name = "example-windows-function-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_account_name = azurerm_storage_account.example.name
storage_account_access_key = azurerm_storage_account.example.primary_access_key
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = false
}

resource "azurerm_windows_function_app_slot" "disabled" {
name = "example-slot"
function_app_id = azurerm_windows_function_app.example.id
storage_account_name = azurerm_storage_account.example.name

public_network_access_enabled = false
}

# fail

resource "azurerm_linux_function_app" "default" {
name = "example-linux-function-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_account_name = azurerm_storage_account.example.name
storage_account_access_key = azurerm_storage_account.example.primary_access_key
service_plan_id = azurerm_service_plan.example.id
}

resource "azurerm_linux_function_app_slot" "default" {
name = "example-linux-function-app-slot"
function_app_id = azurerm_linux_function_app.example.id
storage_account_name = azurerm_storage_account.example.name
}

resource "azurerm_windows_function_app" "default" {
name = "example-windows-function-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_account_name = azurerm_storage_account.example.name
storage_account_access_key = azurerm_storage_account.example.primary_access_key
service_plan_id = azurerm_service_plan.example.id
}

resource "azurerm_windows_function_app_slot" "default" {
name = "example-slot"
function_app_id = azurerm_windows_function_app.example.id
storage_account_name = azurerm_storage_account.example.name
}

resource "azurerm_linux_function_app" "enabled" {
name = "example-linux-function-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_account_name = azurerm_storage_account.example.name
storage_account_access_key = azurerm_storage_account.example.primary_access_key
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = true
}

resource "azurerm_linux_function_app_slot" "enabled" {
name = "example-linux-function-app-slot"
function_app_id = azurerm_linux_function_app.example.id
storage_account_name = azurerm_storage_account.example.name

public_network_access_enabled = true
}

resource "azurerm_windows_function_app" "enabled" {
name = "example-windows-function-app"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_account_name = azurerm_storage_account.example.name
storage_account_access_key = azurerm_storage_account.example.primary_access_key
service_plan_id = azurerm_service_plan.example.id

public_network_access_enabled = true
}

resource "azurerm_windows_function_app_slot" "enabled" {
name = "example-slot"
function_app_id = azurerm_windows_function_app.example.id
storage_account_name = azurerm_storage_account.example.name

public_network_access_enabled = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import unittest
from pathlib import Path

from checkov.runner_filter import RunnerFilter
from checkov.terraform.checks.resource.azure.AppServicePublicAccessDisabled import check
from checkov.terraform.runner import Runner


class TestAppServicePublicAccessDisabled(unittest.TestCase):
def test(self):
# given
test_files_dir = Path(__file__).parent / "example_AppServicePublicAccessDisabled"

# when
report = Runner().run(root_folder=str(test_files_dir), runner_filter=RunnerFilter(checks=[check.id]))

# then
summary = report.get_summary()

passing_resources = {
"azurerm_linux_web_app.disabled",
"azurerm_windows_web_app.disabled",
}

failing_resources = {
"azurerm_linux_web_app.default",
"azurerm_windows_web_app.default",
"azurerm_linux_web_app.enabled",
"azurerm_windows_web_app.enabled",
}

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"], 0)
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()
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import unittest
from pathlib import Path

from checkov.runner_filter import RunnerFilter
from checkov.terraform.checks.resource.azure.FunctionAppPublicAccessDisabled import check
from checkov.terraform.runner import Runner


class TestFunctionAppPublicAccessDisabled(unittest.TestCase):
def test(self):
# given
test_files_dir = Path(__file__).parent / "example_FunctionAppPublicAccessDisabled"

# when
report = Runner().run(root_folder=str(test_files_dir), runner_filter=RunnerFilter(checks=[check.id]))

# then
summary = report.get_summary()

passing_resources = {
"azurerm_linux_function_app.disabled",
"azurerm_linux_function_app_slot.disabled",
"azurerm_windows_function_app.disabled",
"azurerm_windows_function_app_slot.disabled",
}

failing_resources = {
"azurerm_linux_function_app.default",
"azurerm_linux_function_app_slot.default",
"azurerm_windows_function_app.default",
"azurerm_windows_function_app_slot.default",
"azurerm_linux_function_app.enabled",
"azurerm_linux_function_app_slot.enabled",
"azurerm_windows_function_app.enabled",
"azurerm_windows_function_app_slot.enabled",
}

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"], 0)
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()
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def test_app_service_linux_function_resources(mocker: MockerFixture, graph_frame

assert len(tf_report.resources) == 2
assert len(tf_report.passed_checks) == 0
assert len(tf_report.failed_checks) == 0
assert len(tf_report.failed_checks) == 2
assert len(tf_report.skipped_checks) == 0
assert len(tf_report.parsing_errors) == 0

Expand Down Expand Up @@ -181,7 +181,7 @@ def test_app_service_linux_web_resources(mocker: MockerFixture, graph_framework)

assert len(tf_report.resources) == 2
assert len(tf_report.passed_checks) == 4
assert len(tf_report.failed_checks) == 12
assert len(tf_report.failed_checks) == 13
assert len(tf_report.skipped_checks) == 0
assert len(tf_report.parsing_errors) == 0

Expand Down Expand Up @@ -270,7 +270,7 @@ def test_app_service_windows_web_resources(mocker: MockerFixture, graph_framewor

assert len(tf_report.resources) == 2
assert len(tf_report.passed_checks) == 4
assert len(tf_report.failed_checks) == 12
assert len(tf_report.failed_checks) == 13
assert len(tf_report.skipped_checks) == 0
assert len(tf_report.parsing_errors) == 0

Expand Down

0 comments on commit 6b04f95

Please sign in to comment.