Skip to content

Commit fdf56c4

Browse files
committed
feat(netpol): authorize l3 protocols
Signed-off-by: SkalaNetworks <contact@skala.network>
1 parent e14c95e commit fdf56c4

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

mocks/pkg/ovs/interface.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controller/network_policy.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,14 @@ func (c *Controller) handleUpdateNp(key string) error {
174174

175175
if hasIngressRule(np) {
176176
for _, protocol := range protocolSet.List() {
177+
standardACLOps, err := c.OVNNbClient.CreateNpBaseACLOps(npName, pgName, np.Namespace, ovnnb.ACLDirectionToLport, protocol)
178+
if err != nil {
179+
klog.Errorf("failed to set base ingress acl: %v", err)
180+
return fmt.Errorf("failed to set default ingress block acl: %w", err)
181+
}
182+
klog.Infof("standard acl ops of len %d: %v", len(standardACLOps), standardACLOps)
183+
ingressACLOps = append(ingressACLOps, standardACLOps...)
184+
177185
for idx, npr := range np.Spec.Ingress {
178186
// A single address set must contain addresses of the same type and the name must be unique within table, so IPv4 and IPv6 address set should be different
179187
ingressAllowAsName := fmt.Sprintf("%s.%s.%d", ingressAllowAsNamePrefix, protocol, idx)
@@ -303,6 +311,13 @@ func (c *Controller) handleUpdateNp(key string) error {
303311

304312
if hasEgressRule(np) {
305313
for _, protocol := range protocolSet.List() {
314+
standardACLOps, err := c.OVNNbClient.CreateNpBaseACLOps(npName, pgName, np.Namespace, ovnnb.ACLDirectionToLport, protocol)
315+
if err != nil {
316+
klog.Errorf("failed to set base ingress acl: %v", err)
317+
return fmt.Errorf("failed to set default ingress block acl: %w", err)
318+
}
319+
egressACLOps = append(egressACLOps, standardACLOps...)
320+
306321
for idx, npr := range np.Spec.Egress {
307322
// A single address set must contain addresses of the same type and the name must be unique within table, so IPv4 and IPv6 address set should be different
308323
egressAllowAsName := fmt.Sprintf("%s.%s.%d", egressAllowAsNamePrefix, protocol, idx)

pkg/ovs/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ type PortGroup interface {
157157
}
158158

159159
type ACL interface {
160+
CreateNpBaseACLOps(npName, pgName, npNamespace, direction, protocol string) ([]ovsdb.Operation, error)
160161
UpdateIngressACLOps(netpol, pgName, asIngressName, asExceptName, protocol, aclName string, npp []netv1.NetworkPolicyPort, logEnable bool, logACLActions []ovnnb.ACLAction, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error)
161162
UpdateEgressACLOps(netpol, pgName, asEgressName, asExceptName, protocol, aclName string, npp []netv1.NetworkPolicyPort, logEnable bool, logACLActions []ovnnb.ACLAction, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error)
162163
CreateGatewayACL(lsName, pgName, gateway, u2oInterconnectionIP string) error

pkg/ovs/ovn-nb-acl.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,94 @@ func setACLName(acl *ovnnb.ACL, name string) {
5353
acl.Name = ptr.To(name)
5454
}
5555

56+
// CreateNpBaseACLOps creates the base ACLs of a NetworkPolicy to allow ARP/ICMP/VRRP
57+
// We allow those protocols because the standard for NetworkPolicies excepts to only block
58+
// based on the IP/TCP/UDP/SCTP protocols.
59+
func (c *OVNNbClient) CreateNpBaseACLOps(npName, pgName, npNamespace, direction, protocol string) ([]ovsdb.Operation, error) {
60+
portDirection := "outport"
61+
dhcpv4UdpSrc, dhcpv4UdpDst := "67", "68"
62+
dhcpv6UdpSrc, dhcpv6UdpDst := "547", "546"
63+
64+
if direction == ovnnb.ACLDirectionFromLport { // egress rule
65+
portDirection = "inport"
66+
dhcpv4UdpSrc, dhcpv4UdpDst = dhcpv4UdpDst, dhcpv4UdpSrc
67+
dhcpv6UdpSrc, dhcpv6UdpDst = dhcpv6UdpDst, dhcpv6UdpSrc
68+
}
69+
70+
acls := make([]*ovnnb.ACL, 0)
71+
72+
newACL := func(match, protocol string) {
73+
options := func(acl *ovnnb.ACL) {
74+
setACLName(acl, npName)
75+
}
76+
77+
acl, err := c.newACL(pgName, direction, util.IngressAllowPriority, match, ovnnb.ACLActionAllowRelated, util.NetpolACLTier, options)
78+
if err != nil {
79+
klog.Error(err)
80+
klog.Errorf("failed to create new base ingress acl for network policy %s/%s: %v", npNamespace, npName, err)
81+
return
82+
}
83+
acls = append(acls, acl)
84+
}
85+
86+
// Allow ARP
87+
allArpMatch := NewAndACLMatch(
88+
NewACLMatch(portDirection, "==", "@"+pgName, ""),
89+
NewACLMatch("arp", "", "", ""),
90+
)
91+
newACL(allArpMatch.String(), "arp")
92+
93+
// Allow VRRP
94+
vrrpMatch := NewAndACLMatch(
95+
NewACLMatch(portDirection, "==", "@"+pgName, ""),
96+
NewACLMatch("ip.proto", "==", "112", ""),
97+
)
98+
newACL(vrrpMatch.String(), "vrrp")
99+
100+
if protocol == kubeovnv1.ProtocolIPv6 {
101+
// Allow ICMPv6
102+
icmpv6Match := NewAndACLMatch(
103+
NewACLMatch(portDirection, "==", "@"+pgName, ""),
104+
NewACLMatch("icmp6", "", "", ""),
105+
)
106+
newACL(icmpv6Match.String(), "icmp")
107+
108+
// Allow DHCPv6
109+
dhcpv6Match := NewAndACLMatch(
110+
NewACLMatch(portDirection, "==", "@"+pgName, ""),
111+
NewACLMatch("udp.src", "==", dhcpv6UdpSrc, ""),
112+
NewACLMatch("udp.dst", "==", dhcpv6UdpDst, ""),
113+
NewACLMatch("ip6", "", "", ""),
114+
)
115+
newACL(dhcpv6Match.String(), "dhcp")
116+
}
117+
118+
if protocol == kubeovnv1.ProtocolIPv4 {
119+
// Allow ICMPv4
120+
icmpv6Match := NewAndACLMatch(
121+
NewACLMatch(portDirection, "==", "@"+pgName, ""),
122+
NewACLMatch("icmp4", "", "", ""),
123+
)
124+
newACL(icmpv6Match.String(), "icmp")
125+
126+
// Allow DHCPv4
127+
dhcpv4Match := NewAndACLMatch(
128+
NewACLMatch(portDirection, "==", "@"+pgName, ""),
129+
NewACLMatch("udp.src", "==", dhcpv4UdpSrc, ""),
130+
NewACLMatch("udp.dst", "==", dhcpv4UdpDst, ""),
131+
NewACLMatch("ip4", "", "", ""),
132+
)
133+
newACL(dhcpv4Match.String(), "dhcp")
134+
}
135+
136+
ops, err := c.CreateAclsOps(pgName, portGroupKey, acls...)
137+
if err != nil {
138+
klog.Error(err)
139+
return nil, fmt.Errorf("failed to create ingress acl for port group %s: %w", pgName, err)
140+
}
141+
return ops, nil
142+
}
143+
56144
// UpdateIngressACLOps return operation that creates an ingress ACL
57145
func (c *OVNNbClient) UpdateIngressACLOps(netpol, pgName, asIngressName, asExceptName, protocol, aclName string, npp []netv1.NetworkPolicyPort, logEnable bool, logACLActions []ovnnb.ACLAction, namedPortMap map[string]*util.NamedPortInfo) ([]ovsdb.Operation, error) {
58146
acls := make([]*ovnnb.ACL, 0)

0 commit comments

Comments
 (0)