Control: 2.1.2 Ensure that network security groups are configured for Databricks subnets
Description
Network Security Groups (NSGs) should be implemented to control inbound and outbound traffic to Azure Databricks subnets, ensuring only authorized communication. NSGs operate using a rule-based model that includes both explicit allow/deny rules and an implicit deny at the end of the rule list. This means that any traffic not explicitly allowed is automatically denied. To ensure secure and predictable behavior, NSGs should be configured with explicit deny rules for known unwanted traffic, in addition to the default implicit deny, to improve visibility and auditability of blocked traffic. This approach helps enforce least privilege and minimizes the risk of unauthorized access to Databricks resources.
Using NSGs with both explicit allow and deny rules provides clear documentation and control over permitted and prohibited traffic. While Azure NSGs implicitly deny all traffic not explicitly allowed, defining explicit deny rules for known malicious or unnecessary sources enhances clarity, simplifies troubleshooting, and supports compliance audits. This layered approach strengthens the security posture of Databricks environments by ensuring only essential communication is permitted.
Remediation
Remediate from Azure Portal
- Assign NSG to Databricks subnets under Networking > NSG Settings.
Default Value:
By default, Databricks subnets do not have NSGs assigned.
Usage
Run the control in your terminal:
powerpipe control run azure_compliance.control.cis_v500_2_1_2Snapshot and share results via Turbot Pipes:
powerpipe loginpowerpipe control run azure_compliance.control.cis_v500_2_1_2 --shareSQL
This control uses a named query:
with databricks_subnets as ( select id, 'private' as subnet_type, concat(parameters -> 'customVirtualNetworkId' ->> 'value', '/subnets/', parameters -> 'customPrivateSubnetName' ->> 'value') as subnet_id from azure_databricks_workspace where parameters -> 'customVirtualNetworkId' IS NOT NULL and parameters -> 'customPrivateSubnetName' ->> 'value' IS NOT NULL UNION ALL select id, 'public' as subnet_type, concat(parameters -> 'customVirtualNetworkId' ->> 'value', '/subnets/', parameters -> 'customPublicSubnetName' ->> 'value') as subnet_id from azure_databricks_workspace where parameters -> 'customVirtualNetworkId' IS NOT NULL and parameters -> 'customPublicSubnetName' ->> 'value' IS NOT NULL), databricks_subnets_without_nsg as ( select distinct ds.id, network_security_group_id from azure_subnet as s right join databricks_subnets as ds on lower(s.id) = lower(ds.subnet_id) where s.network_security_group_id is null)select a.id as resource, case when parameters -> 'customVirtualNetworkId' is null then 'skip' when nsg.id is null then 'ok' else 'alarm' end as status, case when parameters -> 'customVirtualNetworkId' is null then a.name || ' is not deployed in a customer-managed virtual network.' when nsg.id is null then a.name || ' subnets are configured with network security group.' else a.name || ' subnets are not configured with network security group.' end as reason , a.resource_group as resource_group , sub.display_name as subscriptionfrom azure_databricks_workspace as a left join databricks_subnets_without_nsg as nsg on nsg.id = a.id left join azure_subscription as sub on sub.subscription_id = a.subscription_id;