Add dual stack support to the platform firewall
This change updates the firewall configuration generation to take into account that a network can have more than one address pool associated to it. More tests were added to address dual stack setups. Test plan ========= Online setup tests ------------------ System: - AIO-DX - STANDARD (2 Controllers, 2 Storages, 1 Compute) Acceptance criteria: For all the platform interfaces, incoming ICMP, TCP and UDP traffic is allowed only for networks/ports that are configured in the associated address pools. [PASS] TC1 - Install IPv4, add IPv6 pools to the platform networks [PASS] TC2 - Install IPv6, add IPv4 pools to the platform networks Installation tests ------------------ Systems: AIO-SX, AIO-DX, STANDARD [PASS] TC3 - Regular installation on VirtualBox, IPv4 [PASS] TC4 - Regular installation on VirtualBox, IPv6 Related changes: - https://review.opendev.org/c/starlingx/stx-puppet/+/915509 - https://review.opendev.org/c/starlingx/ansible-playbooks/+/915510 Story: 2011027 Task: 49816 Depends-On: https://review.opendev.org/c/starlingx/config/+/914141 Change-Id: Id05a583e7fd806a6ea448ac5a521902b2c7e96e4 Signed-off-by: Lucas Ratusznei Fonseca <lucas.ratuszneifonseca@windriver.com>
This commit is contained in:
parent
ff3a5d2341
commit
fc8c161df6
|
@ -5905,6 +5905,17 @@ class Connection(api.Connection):
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@db_objects.objectify(objects.address_pool)
|
||||||
|
def address_pools_get_by_network(self, network_id,
|
||||||
|
limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
query = model_query(models.AddressPools)
|
||||||
|
query = (query.join(models.NetworkAddressPools,
|
||||||
|
models.NetworkAddressPools.address_pool_id == models.AddressPools.id))
|
||||||
|
query = query.filter(models.NetworkAddressPools.network_id == network_id)
|
||||||
|
return _paginate_query(models.AddressPools, limit, marker,
|
||||||
|
sort_key, sort_dir, query)
|
||||||
|
|
||||||
def address_pool_destroy(self, address_pool_uuid):
|
def address_pool_destroy(self, address_pool_uuid):
|
||||||
query = model_query(models.AddressPools)
|
query = model_query(models.AddressPools)
|
||||||
query = add_identity_filter(query, address_pool_uuid)
|
query = add_identity_filter(query, address_pool_uuid)
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from netaddr import IPAddress
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from sysinv.common import constants
|
from sysinv.common import constants
|
||||||
from sysinv.common import exception
|
from sysinv.common import exception
|
||||||
|
@ -248,14 +247,9 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
for network in firewall_networks:
|
for network in firewall_networks:
|
||||||
|
|
||||||
gnp_name = host.personality + "-" + network.type + "-if-gnp"
|
gnp_name = host.personality + "-" + network.type + "-if-gnp"
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
|
||||||
nodetype_selector = f"has(nodetype) && nodetype == '{host.personality}'"
|
nodetype_selector = f"has(nodetype) && nodetype == '{host.personality}'"
|
||||||
iftype_selector = f"has(iftype) && iftype contains '{network.type}'"
|
iftype_selector = f"has(iftype) && iftype contains '{network.type}'"
|
||||||
selector = f"{nodetype_selector} && {iftype_selector}"
|
selector = f"{nodetype_selector} && {iftype_selector}"
|
||||||
ICMP = "ICMP"
|
|
||||||
if (ip_version == 6):
|
|
||||||
ICMP = "ICMPv6"
|
|
||||||
|
|
||||||
firewall_gnp = dict()
|
firewall_gnp = dict()
|
||||||
firewall_gnp["apiVersion"] = "crd.projectcalico.org/v1"
|
firewall_gnp["apiVersion"] = "crd.projectcalico.org/v1"
|
||||||
|
@ -270,13 +264,20 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
firewall_gnp["spec"].update({"egress": list()})
|
firewall_gnp["spec"].update({"egress": list()})
|
||||||
firewall_gnp["spec"].update({"ingress": list()})
|
firewall_gnp["spec"].update({"ingress": list()})
|
||||||
|
|
||||||
for proto in ["TCP", "UDP", ICMP]:
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
self._add_gnp_proto_rules(host, network, ip_version, firewall_gnp, proto)
|
for addr_pool in addr_pools:
|
||||||
|
ip_version = addr_pool.family
|
||||||
|
ICMP = "ICMP"
|
||||||
|
if ip_version == 6:
|
||||||
|
ICMP = "ICMPv6"
|
||||||
|
|
||||||
if network.type in IPSEC_NETWORKS:
|
for proto in ["TCP", "UDP", ICMP]:
|
||||||
self._add_gnp_proto_rules(host, network, ip_version, firewall_gnp, "ESP", 50)
|
self._add_gnp_proto_rules(host, network, ip_version, firewall_gnp, proto)
|
||||||
|
|
||||||
config[PLATFORM_FIREWALL_CLASSES[network.type]] = copy.copy(firewall_gnp)
|
if network.type in IPSEC_NETWORKS:
|
||||||
|
self._add_gnp_proto_rules(host, network, ip_version, firewall_gnp, "ESP", 50)
|
||||||
|
|
||||||
|
config[PLATFORM_FIREWALL_CLASSES[network.type]] = firewall_gnp
|
||||||
|
|
||||||
def _set_rules_oam(self, gnp_config, network, host, dc_role):
|
def _set_rules_oam(self, gnp_config, network, host, dc_role):
|
||||||
""" Fill the OAM network specific filtering data
|
""" Fill the OAM network specific filtering data
|
||||||
|
@ -317,15 +318,21 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
elif rule["protocol"] == "UDP":
|
elif rule["protocol"] == "UDP":
|
||||||
rule.update({"destination": {"ports": udp_ports}})
|
rule.update({"destination": {"ports": udp_ports}})
|
||||||
|
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
for addr_pool in addr_pools:
|
||||||
self._add_destination_net_filter(gnp_config["spec"]["ingress"],
|
ip_version = addr_pool.family
|
||||||
f"{addr_pool.network}/{addr_pool.prefix}")
|
self._add_destination_net_filter(gnp_config["spec"]["ingress"],
|
||||||
if (ip_version == 6):
|
f"{addr_pool.network}/{addr_pool.prefix}")
|
||||||
for rule in gnp_config["spec"]["ingress"]:
|
if (ip_version == constants.IPV6_FAMILY):
|
||||||
if rule["protocol"] == "ICMPv6":
|
for rule in gnp_config["spec"]["ingress"]:
|
||||||
rule["destination"]["nets"].append(LINK_LOCAL)
|
if rule["protocol"] == "ICMPv6":
|
||||||
rule["destination"]["nets"].append(LINK_LOCAL_MC)
|
rule["destination"]["nets"].append(LINK_LOCAL)
|
||||||
|
rule["destination"]["nets"].append(LINK_LOCAL_MC)
|
||||||
|
|
||||||
|
def _copy_tcp_rule(self, config, direction, ip_version):
|
||||||
|
for rule in config[direction]:
|
||||||
|
if rule["protocol"] == "TCP" and rule["ipVersion"] == ip_version:
|
||||||
|
return copy.deepcopy(rule)
|
||||||
|
|
||||||
def _set_rules_mgmt(self, gnp_config, network, host):
|
def _set_rules_mgmt(self, gnp_config, network, host):
|
||||||
""" Fill the management network specific filtering data
|
""" Fill the management network specific filtering data
|
||||||
|
@ -333,33 +340,36 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param gnp_config: the dict containing the hiera data to be filled
|
:param gnp_config: the dict containing the hiera data to be filled
|
||||||
:param network: the sysinv.object.network object for this network
|
:param network: the sysinv.object.network object for this network
|
||||||
"""
|
"""
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
for addr_pool in addr_pools:
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
ip_version = addr_pool.family
|
||||||
f"{addr_pool.network}/{addr_pool.prefix}")
|
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
||||||
if (ip_version == 6):
|
f"{addr_pool.network}/{addr_pool.prefix}", ip_version)
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL)
|
|
||||||
if (ip_version == 4):
|
|
||||||
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
|
||||||
# worker/storage nodes request IP dynamically
|
|
||||||
rule = self._get_dhcp_rule(host.personality, "UDP", ip_version)
|
|
||||||
gnp_config["spec"]["ingress"].append(rule)
|
|
||||||
|
|
||||||
# copy the TCP rule and do the same for IGMP
|
if (ip_version == 6):
|
||||||
igmp_proto = 2
|
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL, ip_version)
|
||||||
igmp_egr_rule = copy.deepcopy(gnp_config["spec"]["egress"][0])
|
|
||||||
igmp_egr_rule["protocol"] = igmp_proto
|
if (ip_version == 4):
|
||||||
igmp_egr_rule["metadata"]["annotations"]["name"] = \
|
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
||||||
f"stx-egr-{host.personality}-{network.type}-igmp{ip_version}"
|
# worker/storage nodes request IP dynamically
|
||||||
gnp_config["spec"]["egress"].append(igmp_egr_rule)
|
rule = self._get_dhcp_rule(host.personality, "UDP", constants.IPV4_FAMILY)
|
||||||
igmp_ingr_rule = copy.deepcopy(gnp_config["spec"]["ingress"][0])
|
gnp_config["spec"]["ingress"].append(rule)
|
||||||
igmp_ingr_rule["protocol"] = igmp_proto
|
|
||||||
igmp_ingr_rule["metadata"]["annotations"]["name"] = \
|
# copy the TCP rule and do the same for IGMP
|
||||||
f"stx-ingr-{host.personality}-{network.type}-igmp{ip_version}"
|
igmp_proto = 2
|
||||||
# Allow 0.0.0.0/32 for the case the switch sends IGMP queries from
|
igmp_egr_rule = self._copy_tcp_rule(gnp_config["spec"], "egress", ip_version)
|
||||||
# a VLAN without the IP address configured.
|
igmp_egr_rule["protocol"] = igmp_proto
|
||||||
igmp_ingr_rule["source"]["nets"].append("0.0.0.0/32")
|
igmp_egr_rule["metadata"]["annotations"]["name"] = \
|
||||||
gnp_config["spec"]["ingress"].append(igmp_ingr_rule)
|
f"stx-egr-{host.personality}-{network.type}-igmp{constants.IPV4_FAMILY}"
|
||||||
|
gnp_config["spec"]["egress"].append(igmp_egr_rule)
|
||||||
|
igmp_ingr_rule = self._copy_tcp_rule(gnp_config["spec"], "ingress", ip_version)
|
||||||
|
igmp_ingr_rule["protocol"] = igmp_proto
|
||||||
|
igmp_ingr_rule["metadata"]["annotations"]["name"] = \
|
||||||
|
f"stx-ingr-{host.personality}-{network.type}-igmp{constants.IPV4_FAMILY}"
|
||||||
|
# Allow 0.0.0.0/32 for the case the switch sends IGMP queries from
|
||||||
|
# a VLAN without the IP address configured.
|
||||||
|
igmp_ingr_rule["source"]["nets"].append("0.0.0.0/32")
|
||||||
|
gnp_config["spec"]["ingress"].append(igmp_ingr_rule)
|
||||||
|
|
||||||
def _set_rules_admin(self, gnp_config, network, host):
|
def _set_rules_admin(self, gnp_config, network, host):
|
||||||
""" Fill the admin network specific filtering data
|
""" Fill the admin network specific filtering data
|
||||||
|
@ -367,28 +377,29 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param gnp_config: the dict containing the hiera data to be filled
|
:param gnp_config: the dict containing the hiera data to be filled
|
||||||
:param network: the sysinv.object.network object for this network
|
:param network: the sysinv.object.network object for this network
|
||||||
"""
|
"""
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
for addr_pool in addr_pools:
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
ip_version = addr_pool.family
|
||||||
f"{addr_pool.network}/{addr_pool.prefix}")
|
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
||||||
if (ip_version == 6):
|
f"{addr_pool.network}/{addr_pool.prefix}", ip_version)
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL)
|
if (ip_version == 6):
|
||||||
if (ip_version == 4):
|
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL, ip_version)
|
||||||
# copy the TCP rule and do the same for IGMP
|
if (ip_version == 4):
|
||||||
igmp_proto = 2
|
# copy the TCP rule and do the same for IGMP
|
||||||
igmp_egr_rule = copy.deepcopy(gnp_config["spec"]["egress"][0])
|
igmp_proto = 2
|
||||||
igmp_egr_rule["protocol"] = igmp_proto
|
igmp_egr_rule = self._copy_tcp_rule(gnp_config["spec"], "egress", ip_version)
|
||||||
igmp_egr_rule["metadata"]["annotations"]["name"] = \
|
igmp_egr_rule["protocol"] = igmp_proto
|
||||||
f"stx-egr-{host.personality}-{network.type}-igmp{ip_version}"
|
igmp_egr_rule["metadata"]["annotations"]["name"] = \
|
||||||
gnp_config["spec"]["egress"].append(igmp_egr_rule)
|
f"stx-egr-{host.personality}-{network.type}-igmp{ip_version}"
|
||||||
igmp_ingr_rule = copy.deepcopy(gnp_config["spec"]["ingress"][0])
|
gnp_config["spec"]["egress"].append(igmp_egr_rule)
|
||||||
igmp_ingr_rule["protocol"] = igmp_proto
|
igmp_ingr_rule = self._copy_tcp_rule(gnp_config["spec"], "ingress", ip_version)
|
||||||
igmp_ingr_rule["metadata"]["annotations"]["name"] = \
|
igmp_ingr_rule["protocol"] = igmp_proto
|
||||||
f"stx-ingr-{host.personality}-{network.type}-igmp{ip_version}"
|
igmp_ingr_rule["metadata"]["annotations"]["name"] = \
|
||||||
# Allow 0.0.0.0/32 for the case the switch sends IGMP queries from
|
f"stx-ingr-{host.personality}-{network.type}-igmp{ip_version}"
|
||||||
# a VLAN without the IP address configured.
|
# Allow 0.0.0.0/32 for the case the switch sends IGMP queries from
|
||||||
igmp_ingr_rule["source"]["nets"].append("0.0.0.0/32")
|
# a VLAN without the IP address configured.
|
||||||
gnp_config["spec"]["ingress"].append(igmp_ingr_rule)
|
igmp_ingr_rule["source"]["nets"].append("0.0.0.0/32")
|
||||||
|
gnp_config["spec"]["ingress"].append(igmp_ingr_rule)
|
||||||
|
|
||||||
def _set_rules_cluster_host(self, gnp_config, network, host):
|
def _set_rules_cluster_host(self, gnp_config, network, host):
|
||||||
""" Fill the cluster-host network specific filtering data
|
""" Fill the cluster-host network specific filtering data
|
||||||
|
@ -397,59 +408,64 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param network: the sysinv.object.network object for this network
|
:param network: the sysinv.object.network object for this network
|
||||||
"""
|
"""
|
||||||
|
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
cpod_pool_index = {}
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
|
||||||
f"{addr_pool.network}/{addr_pool.prefix}")
|
|
||||||
|
|
||||||
# add cluster-pod to cover the cases where there is no tunneling, the pod traffic goes
|
|
||||||
# directly in the cluster-host interface
|
|
||||||
cpod_net = self.dbapi.network_get_by_type(constants.NETWORK_TYPE_CLUSTER_POD)
|
cpod_net = self.dbapi.network_get_by_type(constants.NETWORK_TYPE_CLUSTER_POD)
|
||||||
if cpod_net:
|
if cpod_net:
|
||||||
cpod_pool = self.dbapi.address_pool_get(cpod_net.pool_uuid)
|
cpod_pools = self.dbapi.address_pools_get_by_network(cpod_net.id)
|
||||||
cpod_ip_version = IPAddress(f"{cpod_pool.network}").version
|
for cpod_pool in cpod_pools:
|
||||||
if (cpod_ip_version == ip_version):
|
cpod_pool_index[cpod_pool.family] = cpod_pool
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
|
||||||
f"{cpod_pool.network}/{cpod_pool.prefix}")
|
|
||||||
else:
|
else:
|
||||||
LOG.info("Cannot find cluster-pod network to add to cluster-host firewall")
|
LOG.info("Cannot find cluster-pod network to add to cluster-host firewall")
|
||||||
|
|
||||||
# copy the TCP rule and do the same for SCTP
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
sctp_egr_rule = copy.deepcopy(gnp_config["spec"]["egress"][0])
|
for addr_pool in addr_pools:
|
||||||
sctp_egr_rule["protocol"] = "SCTP"
|
ip_version = addr_pool.family
|
||||||
sctp_egr_rule["metadata"]["annotations"]["name"] = \
|
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
||||||
f"stx-egr-{host.personality}-{network.type}-sctp{ip_version}"
|
f"{addr_pool.network}/{addr_pool.prefix}", ip_version)
|
||||||
gnp_config["spec"]["egress"].append(sctp_egr_rule)
|
|
||||||
sctp_ingr_rule = copy.deepcopy(gnp_config["spec"]["ingress"][0])
|
|
||||||
sctp_ingr_rule["protocol"] = "SCTP"
|
|
||||||
sctp_ingr_rule["metadata"]["annotations"]["name"] = \
|
|
||||||
f"stx-ingr-{host.personality}-{network.type}-sctp{ip_version}"
|
|
||||||
gnp_config["spec"]["ingress"].append(sctp_ingr_rule)
|
|
||||||
|
|
||||||
if (ip_version == 6):
|
# add cluster-pod to cover the cases where there is no tunneling, the pod traffic goes
|
||||||
# add link-local network too
|
# directly in the cluster-host interface
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL)
|
cpod_pool = cpod_pool_index.get(ip_version, None)
|
||||||
|
if cpod_pool:
|
||||||
|
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
||||||
|
f"{cpod_pool.network}/{cpod_pool.prefix}", ip_version)
|
||||||
|
|
||||||
if (ip_version == 4):
|
# copy the TCP rule and do the same for SCTP
|
||||||
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
sctp_egr_rule = self._copy_tcp_rule(gnp_config["spec"], "egress", ip_version)
|
||||||
rule = self._get_dhcp_rule(host.personality, "UDP", ip_version)
|
sctp_egr_rule["protocol"] = "SCTP"
|
||||||
gnp_config["spec"]["ingress"].append(rule)
|
sctp_egr_rule["metadata"]["annotations"]["name"] = \
|
||||||
|
f"stx-egr-{host.personality}-{network.type}-sctp{ip_version}"
|
||||||
|
gnp_config["spec"]["egress"].append(sctp_egr_rule)
|
||||||
|
sctp_ingr_rule = self._copy_tcp_rule(gnp_config["spec"], "ingress", ip_version)
|
||||||
|
sctp_ingr_rule["protocol"] = "SCTP"
|
||||||
|
sctp_ingr_rule["metadata"]["annotations"]["name"] = \
|
||||||
|
f"stx-ingr-{host.personality}-{network.type}-sctp{ip_version}"
|
||||||
|
gnp_config["spec"]["ingress"].append(sctp_ingr_rule)
|
||||||
|
|
||||||
# copy the TCP rule and do the same for IGMP
|
if (ip_version == 6):
|
||||||
igmp_proto = 2
|
# add link-local network too
|
||||||
igmp_egr_rule = copy.deepcopy(gnp_config["spec"]["egress"][0])
|
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL, ip_version)
|
||||||
igmp_egr_rule["protocol"] = igmp_proto
|
|
||||||
igmp_egr_rule["metadata"]["annotations"]["name"] = \
|
if (ip_version == 4):
|
||||||
f"stx-egr-{host.personality}-{network.type}-igmp{ip_version}"
|
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
||||||
gnp_config["spec"]["egress"].append(igmp_egr_rule)
|
rule = self._get_dhcp_rule(host.personality, "UDP", ip_version)
|
||||||
igmp_ingr_rule = copy.deepcopy(gnp_config["spec"]["ingress"][0])
|
gnp_config["spec"]["ingress"].append(rule)
|
||||||
igmp_ingr_rule["protocol"] = igmp_proto
|
|
||||||
igmp_ingr_rule["metadata"]["annotations"]["name"] = \
|
# copy the TCP rule and do the same for IGMP
|
||||||
f"stx-ingr-{host.personality}-{network.type}-igmp{ip_version}"
|
igmp_proto = 2
|
||||||
# Allow 0.0.0.0/32 for the case the switch sends IGMP queries from
|
igmp_egr_rule = self._copy_tcp_rule(gnp_config["spec"], "egress", ip_version)
|
||||||
# a VLAN without the IP address configured.
|
igmp_egr_rule["protocol"] = igmp_proto
|
||||||
igmp_ingr_rule["source"]["nets"].append("0.0.0.0/32")
|
igmp_egr_rule["metadata"]["annotations"]["name"] = \
|
||||||
gnp_config["spec"]["ingress"].append(igmp_ingr_rule)
|
f"stx-egr-{host.personality}-{network.type}-igmp{ip_version}"
|
||||||
|
gnp_config["spec"]["egress"].append(igmp_egr_rule)
|
||||||
|
igmp_ingr_rule = self._copy_tcp_rule(gnp_config["spec"], "ingress", ip_version)
|
||||||
|
igmp_ingr_rule["protocol"] = igmp_proto
|
||||||
|
igmp_ingr_rule["metadata"]["annotations"]["name"] = \
|
||||||
|
f"stx-ingr-{host.personality}-{network.type}-igmp{ip_version}"
|
||||||
|
# Allow 0.0.0.0/32 for the case the switch sends IGMP queries from
|
||||||
|
# a VLAN without the IP address configured.
|
||||||
|
igmp_ingr_rule["source"]["nets"].append("0.0.0.0/32")
|
||||||
|
gnp_config["spec"]["ingress"].append(igmp_ingr_rule)
|
||||||
|
|
||||||
def _set_rules_pxeboot(self, gnp_config, network, host):
|
def _set_rules_pxeboot(self, gnp_config, network, host):
|
||||||
""" Fill the pxeboot network specific filtering data
|
""" Fill the pxeboot network specific filtering data
|
||||||
|
@ -458,16 +474,17 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param network: the sysinv.object.network object for this network
|
:param network: the sysinv.object.network object for this network
|
||||||
"""
|
"""
|
||||||
|
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
for addr_pool in addr_pools:
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
ip_version = addr_pool.family
|
||||||
f"{addr_pool.network}/{addr_pool.prefix}")
|
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
||||||
if (ip_version == 6):
|
f"{addr_pool.network}/{addr_pool.prefix}", ip_version)
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL)
|
if (ip_version == 6):
|
||||||
if (ip_version == 4):
|
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL, ip_version)
|
||||||
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
if (ip_version == 4):
|
||||||
rule = self._get_dhcp_rule(host.personality, "UDP", ip_version)
|
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
||||||
gnp_config["spec"]["ingress"].append(rule)
|
rule = self._get_dhcp_rule(host.personality, "UDP", ip_version)
|
||||||
|
gnp_config["spec"]["ingress"].append(rule)
|
||||||
|
|
||||||
def _set_rules_storage(self, gnp_config, network, host):
|
def _set_rules_storage(self, gnp_config, network, host):
|
||||||
""" Fill the storage network specific filtering data
|
""" Fill the storage network specific filtering data
|
||||||
|
@ -476,18 +493,19 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param network: the sysinv.object.network object for this network
|
:param network: the sysinv.object.network object for this network
|
||||||
"""
|
"""
|
||||||
|
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
for addr_pool in addr_pools:
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
ip_version = addr_pool.family
|
||||||
f"{addr_pool.network}/{addr_pool.prefix}")
|
self._add_source_net_filter(gnp_config["spec"]["ingress"],
|
||||||
if (ip_version == 6):
|
f"{addr_pool.network}/{addr_pool.prefix}", ip_version)
|
||||||
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL)
|
if (ip_version == 6):
|
||||||
if (ip_version == 4):
|
self._add_source_net_filter(gnp_config["spec"]["ingress"], LINK_LOCAL, ip_version)
|
||||||
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
if (ip_version == 4):
|
||||||
rule = self._get_dhcp_rule(host.personality, "UDP", ip_version)
|
# add rule to allow DHCP requests (dhcp-offer have src addr == 0.0.0.0)
|
||||||
gnp_config["spec"]["ingress"].append(rule)
|
rule = self._get_dhcp_rule(host.personality, "UDP", ip_version)
|
||||||
|
gnp_config["spec"]["ingress"].append(rule)
|
||||||
|
|
||||||
def _add_source_net_filter(self, rule_list, source_net):
|
def _add_source_net_filter(self, rule_list, source_net, ip_version):
|
||||||
""" Add source network in the rule list
|
""" Add source network in the rule list
|
||||||
|
|
||||||
:param rule_list: the list containing the firewall rules that need to receive the source
|
:param rule_list: the list containing the firewall rules that need to receive the source
|
||||||
|
@ -495,6 +513,8 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param source_net: the string containing the value
|
:param source_net: the string containing the value
|
||||||
"""
|
"""
|
||||||
for rule in rule_list:
|
for rule in rule_list:
|
||||||
|
if rule["ipVersion"] != ip_version:
|
||||||
|
continue
|
||||||
if ("source" in rule.keys()):
|
if ("source" in rule.keys()):
|
||||||
if ("nets" in rule["source"].keys()):
|
if ("nets" in rule["source"].keys()):
|
||||||
rule["source"]["nets"].append(source_net)
|
rule["source"]["nets"].append(source_net)
|
||||||
|
@ -527,33 +547,35 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param host_personality: the node personality (controller, storage, or worker)
|
:param host_personality: the node personality (controller, storage, or worker)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
routes_networks = self._get_routes_networks(network.type)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
|
||||||
ICMP = "ICMP"
|
|
||||||
if ip_version == 6:
|
|
||||||
ICMP = "ICMPv6"
|
|
||||||
|
|
||||||
rules = list()
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
for proto in ["TCP", "UDP", ICMP]:
|
for addr_pool in addr_pools:
|
||||||
rule = {"metadata": dict()}
|
ip_version = addr_pool.family
|
||||||
rule["metadata"] = {"annotations": dict()}
|
ICMP = "ICMP"
|
||||||
rule["metadata"]["annotations"] = {"name":
|
if ip_version == 6:
|
||||||
f"stx-ingr-{host_personality}-subcloud-{proto.lower()}{ip_version}"}
|
ICMP = "ICMPv6"
|
||||||
rule.update({"protocol": proto})
|
|
||||||
rule.update({"ipVersion": ip_version})
|
|
||||||
rule.update({"action": "Allow"})
|
|
||||||
if (proto == "TCP"):
|
|
||||||
rule.update({"destination": {"ports": self._get_subcloud_tcp_ports()}})
|
|
||||||
elif (proto == "UDP"):
|
|
||||||
rule.update({"destination": {"ports": self._get_subcloud_udp_ports()}})
|
|
||||||
rules.append(rule)
|
|
||||||
|
|
||||||
networks = self._get_routes_networks(network.type)
|
rules = list()
|
||||||
for network in networks:
|
for proto in ["TCP", "UDP", ICMP]:
|
||||||
self._add_source_net_filter(rules, network)
|
rule = {"metadata": dict()}
|
||||||
|
rule["metadata"] = {"annotations": dict()}
|
||||||
|
rule["metadata"]["annotations"] = {"name":
|
||||||
|
f"stx-ingr-{host_personality}-subcloud-{proto.lower()}{ip_version}"}
|
||||||
|
rule.update({"protocol": proto})
|
||||||
|
rule.update({"ipVersion": ip_version})
|
||||||
|
rule.update({"action": "Allow"})
|
||||||
|
if (proto == "TCP"):
|
||||||
|
rule.update({"destination": {"ports": self._get_subcloud_tcp_ports()}})
|
||||||
|
elif (proto == "UDP"):
|
||||||
|
rule.update({"destination": {"ports": self._get_subcloud_udp_ports()}})
|
||||||
|
rules.append(rule)
|
||||||
|
|
||||||
for rule in rules:
|
for route_network in routes_networks[ip_version]:
|
||||||
gnp_config["spec"]["ingress"].append(rule)
|
self._add_source_net_filter(rules, route_network, ip_version)
|
||||||
|
|
||||||
|
for rule in rules:
|
||||||
|
gnp_config["spec"]["ingress"].append(rule)
|
||||||
|
|
||||||
def _set_rules_subcloud_mgmt(self, gnp_config, network, host_personality):
|
def _set_rules_subcloud_mgmt(self, gnp_config, network, host_personality):
|
||||||
""" Add filtering rules for mgmt network in a subcloud installation
|
""" Add filtering rules for mgmt network in a subcloud installation
|
||||||
|
@ -566,41 +588,46 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param host_personality: the node personality (controller, storage, or worker)
|
:param host_personality: the node personality (controller, storage, or worker)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
routes_networks = self._get_routes_networks(network.type)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
|
||||||
ICMP = "ICMP"
|
|
||||||
if ip_version == 6:
|
|
||||||
ICMP = "ICMPv6"
|
|
||||||
|
|
||||||
rules = list()
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
for proto in ["TCP", "UDP", ICMP]:
|
for addr_pool in addr_pools:
|
||||||
rule = {"metadata": dict()}
|
ip_version = addr_pool.family
|
||||||
rule["metadata"] = {"annotations": dict()}
|
ICMP = "ICMP"
|
||||||
rule["metadata"]["annotations"] = {"name":
|
if ip_version == 6:
|
||||||
f"stx-ingr-{host_personality}-subcloud-{proto.lower()}{ip_version}"}
|
ICMP = "ICMPv6"
|
||||||
rule.update({"protocol": proto})
|
|
||||||
rule.update({"ipVersion": ip_version})
|
|
||||||
rule.update({"action": "Allow"})
|
|
||||||
if (proto == "TCP"):
|
|
||||||
rule.update({"destination": {"ports": self._get_subcloud_tcp_ports()}})
|
|
||||||
elif (proto == "UDP"):
|
|
||||||
rule.update({"destination": {"ports": self._get_subcloud_udp_ports()}})
|
|
||||||
gnp_config["spec"]["ingress"].append(rule)
|
|
||||||
rules.append(rule)
|
|
||||||
|
|
||||||
networks = self._get_routes_networks(network.type)
|
rules = list()
|
||||||
for network in networks:
|
for proto in ["TCP", "UDP", ICMP]:
|
||||||
self._add_source_net_filter(rules, network)
|
rule = {"metadata": dict()}
|
||||||
|
rule["metadata"] = {"annotations": dict()}
|
||||||
|
rule["metadata"]["annotations"] = {"name":
|
||||||
|
f"stx-ingr-{host_personality}-subcloud-{proto.lower()}{ip_version}"}
|
||||||
|
rule.update({"protocol": proto})
|
||||||
|
rule.update({"ipVersion": ip_version})
|
||||||
|
rule.update({"action": "Allow"})
|
||||||
|
if (proto == "TCP"):
|
||||||
|
rule.update({"destination": {"ports": self._get_subcloud_tcp_ports()}})
|
||||||
|
elif (proto == "UDP"):
|
||||||
|
rule.update({"destination": {"ports": self._get_subcloud_udp_ports()}})
|
||||||
|
gnp_config["spec"]["ingress"].append(rule)
|
||||||
|
rules.append(rule)
|
||||||
|
|
||||||
|
for route_network in routes_networks[ip_version]:
|
||||||
|
self._add_source_net_filter(rules, route_network, ip_version)
|
||||||
|
|
||||||
def _get_routes_networks(self, network_type):
|
def _get_routes_networks(self, network_type):
|
||||||
routes = self.dbapi.routes_get_by_network_type_and_host_personality(
|
routes = self.dbapi.routes_get_by_network_type_and_host_personality(
|
||||||
network_type, constants.CONTROLLER)
|
network_type, constants.CONTROLLER)
|
||||||
networks = set()
|
network_sets = {constants.IPV4_FAMILY: set(), constants.IPV6_FAMILY: set()}
|
||||||
|
networks = {}
|
||||||
for route in routes:
|
for route in routes:
|
||||||
network = route.network + '/' + str(route.prefix)
|
network = route.network + '/' + str(route.prefix)
|
||||||
networks.add(network)
|
network_sets[int(route.family)].add(network)
|
||||||
networks = list(networks)
|
for family, net_set in network_sets.items():
|
||||||
networks.sort()
|
net_list = list(net_set)
|
||||||
|
net_list.sort()
|
||||||
|
networks[family] = net_list
|
||||||
return networks
|
return networks
|
||||||
|
|
||||||
def _set_rules_systemcontroller(self, gnp_config, network, host_personality):
|
def _set_rules_systemcontroller(self, gnp_config, network, host_personality):
|
||||||
|
@ -611,68 +638,38 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
:param host_personality: the node personality (controller, storage, or worker)
|
:param host_personality: the node personality (controller, storage, or worker)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
routes_networks = self._get_routes_networks(network.type)
|
||||||
|
|
||||||
rules = []
|
rules = []
|
||||||
addr_pool = self.dbapi.address_pool_get(network.pool_uuid)
|
addr_pools = self.dbapi.address_pools_get_by_network(network.id)
|
||||||
ip_version = IPAddress(f"{addr_pool.network}").version
|
for addr_pool in addr_pools:
|
||||||
ICMP = "ICMP"
|
ip_version = addr_pool.family
|
||||||
if ip_version == 6:
|
ICMP = "ICMP"
|
||||||
ICMP = "ICMPv6"
|
if ip_version == 6:
|
||||||
|
ICMP = "ICMPv6"
|
||||||
|
|
||||||
for proto in ["TCP", "UDP", ICMP]:
|
for proto in ["TCP", "UDP", ICMP]:
|
||||||
rule = {"metadata": dict()}
|
rule = {"metadata": dict()}
|
||||||
rule["metadata"] = {"annotations": dict()}
|
rule["metadata"] = {"annotations": dict()}
|
||||||
rule["metadata"]["annotations"] = {"name":
|
rule["metadata"]["annotations"] = {"name":
|
||||||
f"stx-ingr-{host_personality}-systemcontroller-{proto.lower()}{ip_version}"}
|
f"stx-ingr-{host_personality}-systemcontroller-{proto.lower()}{ip_version}"}
|
||||||
rule.update({"protocol": proto})
|
rule.update({"protocol": proto})
|
||||||
rule.update({"ipVersion": ip_version})
|
rule.update({"ipVersion": ip_version})
|
||||||
rule.update({"action": "Allow"})
|
rule.update({"action": "Allow"})
|
||||||
if (proto == "TCP"):
|
if (proto == "TCP"):
|
||||||
tcp_list = self._get_systemcontroller_tcp_ports()
|
tcp_list = self._get_systemcontroller_tcp_ports()
|
||||||
rule.update({"destination": {"ports": tcp_list}})
|
rule.update({"destination": {"ports": tcp_list}})
|
||||||
elif (proto == "UDP"):
|
elif (proto == "UDP"):
|
||||||
udp_list = self._get_systemcontroller_udp_ports()
|
udp_list = self._get_systemcontroller_udp_ports()
|
||||||
rule.update({"destination": {"ports": udp_list}})
|
rule.update({"destination": {"ports": udp_list}})
|
||||||
gnp_config["spec"]["ingress"].append(rule)
|
gnp_config["spec"]["ingress"].append(rule)
|
||||||
rules.append(rule)
|
rules.append(rule)
|
||||||
|
|
||||||
networks = self._get_routes_networks(network.type)
|
for route_network in routes_networks[ip_version]:
|
||||||
for network in networks:
|
self._add_source_net_filter(rules, route_network, ip_version)
|
||||||
self._add_source_net_filter(rules, network)
|
|
||||||
|
|
||||||
def _set_extra_rules(self, config):
|
def _set_extra_rules(self, config):
|
||||||
self._ingress_ipv6_for_ipv4_install_case(config)
|
pass
|
||||||
return
|
|
||||||
|
|
||||||
def _ingress_ipv6_for_ipv4_install_case(self, full_config):
|
|
||||||
|
|
||||||
intf_ip_version = dict()
|
|
||||||
for hep in full_config[FIREWALL_HE_INTERFACE_CFG].keys():
|
|
||||||
hep_data = full_config[FIREWALL_HE_INTERFACE_CFG][hep]
|
|
||||||
iftype_list = (hep_data['metadata']['labels']['iftype']).split('.')
|
|
||||||
interface = hep_data['spec']['interfaceName']
|
|
||||||
intf_ip_version.update({interface: set()})
|
|
||||||
for iftype in iftype_list:
|
|
||||||
for gnp_config in full_config.keys():
|
|
||||||
if (gnp_config == FIREWALL_HE_INTERFACE_CFG
|
|
||||||
or gnp_config == FIREWALL_EXTRA_FILTER_CFG):
|
|
||||||
continue
|
|
||||||
if not full_config[gnp_config]:
|
|
||||||
continue
|
|
||||||
gnp_data = full_config[gnp_config]
|
|
||||||
if (iftype in gnp_data['spec']['selector']):
|
|
||||||
for ingress in gnp_data['spec']['ingress']:
|
|
||||||
intf_ip_version[interface].add(ingress['ipVersion'])
|
|
||||||
|
|
||||||
is_ipv4_install = True
|
|
||||||
for intf in intf_ip_version.keys():
|
|
||||||
if (6 in intf_ip_version[intf]):
|
|
||||||
is_ipv4_install = False
|
|
||||||
break
|
|
||||||
|
|
||||||
if is_ipv4_install:
|
|
||||||
full_config[FIREWALL_EXTRA_FILTER_CFG].update(
|
|
||||||
{"ingress-ipv6-for-ipv4-install": list(intf_ip_version.keys())})
|
|
||||||
return
|
|
||||||
|
|
||||||
def _get_subcloud_tcp_ports(self):
|
def _get_subcloud_tcp_ports(self):
|
||||||
""" Get the TCP L4 ports for subclouds
|
""" Get the TCP L4 ports for subclouds
|
||||||
|
@ -768,12 +765,13 @@ class PlatformFirewallPuppet(base.BasePuppet):
|
||||||
elif host.hostname == constants.CONTROLLER_1_HOSTNAME:
|
elif host.hostname == constants.CONTROLLER_1_HOSTNAME:
|
||||||
address_name = cutils.format_address_name(constants.CONTROLLER_1_HOSTNAME, net_type)
|
address_name = cutils.format_address_name(constants.CONTROLLER_1_HOSTNAME, net_type)
|
||||||
|
|
||||||
address = cutils.get_primary_address_by_name(self.dbapi, address_name, net_type)
|
addresses = self.dbapi.address_get_by_name(address_name)
|
||||||
if (address):
|
address_texts = [str(address.address) for address in addresses]
|
||||||
|
if (address_texts):
|
||||||
if ("expectedIPs" in host_endpoints["spec"].keys()):
|
if ("expectedIPs" in host_endpoints["spec"].keys()):
|
||||||
host_endpoints["spec"]["expectedIPs"].append(str(address.address))
|
host_endpoints["spec"]["expectedIPs"].extend(address_texts)
|
||||||
else:
|
else:
|
||||||
host_endpoints["spec"].update({"expectedIPs": [str(address.address)]})
|
host_endpoints["spec"].update({"expectedIPs": address_texts})
|
||||||
else:
|
else:
|
||||||
LOG.info(f"cannot find address:{address_name} for net_type:{net_type} expectedIPs")
|
LOG.info(f"cannot find address:{address_name} for net_type:{net_type} expectedIPs")
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue