Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion scripts/caclmgrd
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
"dst_ports": ["22"],
"multi_asic_ns_to_host_fwd":True
},
"EXTERNAL_CLIENT": {
"ip_protocols": ["tcp"],
"multi_asic_ns_to_host_fwd":True
},
"ANY": {
"ip_protocols": ["any"],
"dst_ports": ["0"],
Expand Down Expand Up @@ -545,7 +549,8 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):

# Obtain default IP protocol(s) and destination port(s) for this service
ip_protocols = self.ACL_SERVICES[acl_service]["ip_protocols"]
dst_ports = self.ACL_SERVICES[acl_service]["dst_ports"]
if "dst_ports" in self.ACL_SERVICES[acl_service]:
dst_ports = self.ACL_SERVICES[acl_service]["dst_ports"]

acl_rules = {}

Expand All @@ -571,6 +576,19 @@ class ControlPlaneAclManager(daemon_base.DaemonBase):
elif self.is_rule_ipv4(rule_props):
table_ip_version = 4

# Read DST_PORT info from Config DB, insert it back to ACL_SERVICES
if acl_service == 'EXTERNAL_CLIENT' and "L4_DST_PORT" in rule_props:
dst_ports = [rule_props["L4_DST_PORT"]]
self.ACL_SERVICES[acl_service]["dst_ports"] = dst_ports
elif acl_service == 'EXTERNAL_CLIENT' and "L4_DST_PORT_RANGE" in rule_props:
dst_ports = []
port_ranges = rule_props["L4_DST_PORT_RANGE"].split("-")
port_start = int(port_ranges[0])
port_end = int(port_ranges[1])
for port in range(port_start, port_end + 1):
dst_ports.append(port)
self.ACL_SERVICES[acl_service]["dst_ports"] = dst_ports

if (self.is_rule_ipv6(rule_props) and (table_ip_version == 4)):
self.log_error("CtrlPlane ACL table {} is a IPv4 based table and rule {} is a IPV6 rule! Ignoring rule."
.format(table_name, rule_id))
Expand Down
44 changes: 44 additions & 0 deletions tests/caclmgrd/caclmgrd_external_client_acl_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import os
import sys

from swsscommon import swsscommon
from parameterized import parameterized
from sonic_py_common.general import load_module_from_source
from unittest import TestCase, mock
from pyfakefs.fake_filesystem_unittest import patchfs

from .test_external_client_acl_vectors import EXTERNAL_CLIENT_ACL_TEST_VECTOR
from tests.common.mock_configdb import MockConfigDb


DBCONFIG_PATH = '/var/run/redis/sonic-db/database_config.json'


class TestCaclmgrdExternalClientAcl(TestCase):
"""
Test caclmgrd EXTERNAL_CLIENT_ACL
"""
def setUp(self):
swsscommon.ConfigDBConnector = MockConfigDb
test_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
modules_path = os.path.dirname(test_path)
scripts_path = os.path.join(modules_path, "scripts")
sys.path.insert(0, modules_path)
caclmgrd_path = os.path.join(scripts_path, 'caclmgrd')
self.caclmgrd = load_module_from_source('caclmgrd', caclmgrd_path)

@parameterized.expand(EXTERNAL_CLIENT_ACL_TEST_VECTOR)
@patchfs
def test_caclmgrd_external_client_acl(self, test_name, test_data, fs):
if not os.path.exists(DBCONFIG_PATH):
fs.create_file(DBCONFIG_PATH) # fake database_config.json

MockConfigDb.set_config_db(test_data["config_db"])
self.caclmgrd.ControlPlaneAclManager.get_namespace_mgmt_ip = mock.MagicMock()
self.caclmgrd.ControlPlaneAclManager.get_namespace_mgmt_ipv6 = mock.MagicMock()
self.caclmgrd.ControlPlaneAclManager.generate_block_ip2me_traffic_iptables_commands = mock.MagicMock(return_value=[])
self.caclmgrd.ControlPlaneAclManager.get_chain_list = mock.MagicMock(return_value=["INPUT", "FORWARD", "OUTPUT"])
caclmgrd_daemon = self.caclmgrd.ControlPlaneAclManager("caclmgrd")

iptables_rules_ret, _ = caclmgrd_daemon.get_acl_rules_and_translate_to_iptables_commands('')
self.assertEqual(set(test_data["return"]).issubset(set(iptables_rules_ret)), True)
167 changes: 167 additions & 0 deletions tests/caclmgrd/test_external_client_acl_vectors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
from unittest.mock import call

"""
caclmgrd test external_client_acl vector
"""
EXTERNAL_CLIENT_ACL_TEST_VECTOR = [
[
"Test single IPv4 dst port + src ip for EXTERNAL_CLIENT_ACL",
{
"config_db": {
"ACL_TABLE": {
"EXTERNAL_CLIENT_ACL": {
"stage": "INGRESS",
"type": "CTRLPLANE",
"services": [
"EXTERNAL_CLIENT"
]
}
},
"ACL_RULE": {
"EXTERNAL_CLIENT_ACL|DEFAULT_RULE": {
"ETHER_TYPE": "2048",
"PACKET_ACTION": "DROP",
"PRIORITY": "1"
},
"EXTERNAL_CLIENT_ACL|RULE_1": {
"L4_DST_PORT": "8081",
"PACKET_ACTION": "ACCEPT",
"PRIORITY": "9998",
"SRC_IP": "20.0.0.55/32"
},
},
"DEVICE_METADATA": {
"localhost": {
}
},
"FEATURE": {},
},
"return": [
"iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8081 -j ACCEPT",
"iptables -A INPUT -p tcp --dport 8081 -j DROP"
],
}
],
[
"Test IPv4 dst port range + src ip forEXTERNAL_CLIENT_ACL",
{
"config_db": {
"ACL_TABLE": {
"EXTERNAL_CLIENT_ACL": {
"stage": "INGRESS",
"type": "CTRLPLANE",
"services": [
"EXTERNAL_CLIENT"
]
}
},
"ACL_RULE": {
"EXTERNAL_CLIENT_ACL|DEFAULT_RULE": {
"ETHER_TYPE": "2048",
"PACKET_ACTION": "DROP",
"PRIORITY": "1"
},
"EXTERNAL_CLIENT_ACL|RULE_1": {
"L4_DST_PORT_RANGE": "8081-8083",
"PACKET_ACTION": "ACCEPT",
"PRIORITY": "9998",
"SRC_IP": "20.0.0.55/32"
},
},
"DEVICE_METADATA": {
"localhost": {
}
},
"FEATURE": {},
},
"return": [
"iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8081 -j ACCEPT",
"iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8082 -j ACCEPT",
"iptables -A INPUT -p tcp -s 20.0.0.55/32 --dport 8083 -j ACCEPT",
"iptables -A INPUT -p tcp --dport 8081 -j DROP",
"iptables -A INPUT -p tcp --dport 8082 -j DROP",
"iptables -A INPUT -p tcp --dport 8083 -j DROP",
],
}
],
[
"Test IPv6 single dst port range + src ip forEXTERNAL_CLIENT_ACL",
{
"config_db": {
"ACL_TABLE": {
"EXTERNAL_CLIENT_ACL": {
"stage": "INGRESS",
"type": "CTRLPLANE",
"services": [
"EXTERNAL_CLIENT"
]
}
},
"ACL_RULE": {
"EXTERNAL_CLIENT_ACL|DEFAULT_RULE": {
"ETHER_TYPE": "2048",
"PACKET_ACTION": "DROP",
"PRIORITY": "1"
},
"EXTERNAL_CLIENT_ACL|RULE_1": {
"L4_DST_PORT": "8081",
"PACKET_ACTION": "ACCEPT",
"PRIORITY": "9998",
"SRC_IP": "2001::2/128"
},
},
"DEVICE_METADATA": {
"localhost": {
}
},
"FEATURE": {},
},
"return": [
"iptables -A INPUT -p tcp -s 2001::2/128 --dport 8081 -j ACCEPT",
"iptables -A INPUT -p tcp --dport 8081 -j DROP"
],
}
],
[
"Test IPv6 dst port range + src ip forEXTERNAL_CLIENT_ACL",
{
"config_db": {
"ACL_TABLE": {
"EXTERNAL_CLIENT_ACL": {
"stage": "INGRESS",
"type": "CTRLPLANE",
"services": [
"EXTERNAL_CLIENT"
]
}
},
"ACL_RULE": {
"EXTERNAL_CLIENT_ACL|DEFAULT_RULE": {
"ETHER_TYPE": "2048",
"PACKET_ACTION": "DROP",
"PRIORITY": "1"
},
"EXTERNAL_CLIENT_ACL|RULE_1": {
"L4_DST_PORT_RANGE": "8081-8083",
"PACKET_ACTION": "ACCEPT",
"PRIORITY": "9998",
"SRC_IP": "2001::2/128"
},
},
"DEVICE_METADATA": {
"localhost": {
}
},
"FEATURE": {},
},
"return": [
"iptables -A INPUT -p tcp -s 2001::2/128 --dport 8081 -j ACCEPT",
"iptables -A INPUT -p tcp -s 2001::2/128 --dport 8082 -j ACCEPT",
"iptables -A INPUT -p tcp -s 2001::2/128 --dport 8083 -j ACCEPT",
"iptables -A INPUT -p tcp --dport 8081 -j DROP",
"iptables -A INPUT -p tcp --dport 8082 -j DROP",
"iptables -A INPUT -p tcp --dport 8083 -j DROP",
],
}
]
]