Skip to content
Open
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
31 changes: 22 additions & 9 deletions api/v1/clusterwidenetworkpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)

type IPVersion string
Expand Down Expand Up @@ -100,7 +99,7 @@ type IngressRule struct {
// If this field is present and contains at least one item, then this rule allows
// traffic only if the traffic matches at least one port in the list.
// +optional
Ports []networking.NetworkPolicyPort `json:"ports,omitempty"`
Ports []NetworkPolicyPort `json:"ports,omitempty"`

// List of sources which should be able to access the cluster for this rule.
// Items in this list are combined using a logical OR operation. If this field is
Expand All @@ -120,7 +119,7 @@ type EgressRule struct {
// If this field is present and contains at least one item, then this rule allows
// traffic only if the traffic matches at least one port in the list.
// +optional
Ports []networking.NetworkPolicyPort `json:"ports,omitempty"`
Ports []NetworkPolicyPort `json:"ports,omitempty"`

// List of destinations for outgoing traffic of a cluster for this rule.
// Items in this list are combined using a logical OR operation. If this field is
Expand All @@ -139,6 +138,24 @@ type EgressRule struct {
ToFQDNs []FQDNSelector `json:"toFQDNs,omitempty"`
}

// NetworkPolicyPort describes a port to allow traffic on
type NetworkPolicyPort struct {
// protocol represents the protocol (TCP, UDP) which traffic must match.
// If not specified, this field defaults to TCP.
// +optional
Protocol *corev1.Protocol `json:"protocol,omitempty"`

// port represents the port on the given protocol.
Port int32 `json:"port,omitempty"`

// endPort indicates that the range of ports from port to endPort if set, inclusive,
// should be allowed by the policy. This field cannot be defined if the port field
// is not defined.
// The endPort must be equal or greater than port.
// +optional
EndPort *int32 `json:"endPort,omitempty"`
}

// FQDNSelector describes rules for matching DNS names.
type FQDNSelector struct {
// MatchName matches FQDN.
Expand Down Expand Up @@ -223,14 +240,10 @@ func (p *PolicySpec) Validate() error {
return errors.Join(errs...)
}

func validatePorts(ports []networking.NetworkPolicyPort) error {
func validatePorts(ports []NetworkPolicyPort) error {
var errs []error
for _, p := range ports {
if p.Port != nil && p.Port.Type != intstr.Int {
errs = append(errs, fmt.Errorf("only int ports are supported, but %v given", p.Port))
}

if p.Port != nil && (p.Port.IntValue() > 65535 || p.Port.IntValue() <= 0) {
if p.Port > 65535 || p.Port <= 0 {
errs = append(errs, fmt.Errorf("only ports between 0 and 65535 are allowed, but %v given", p.Port))
}

Expand Down
51 changes: 14 additions & 37 deletions api/v1/clusterwidenetworkpolicy_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import (

corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)

func TestPolicySpec_Validate(t *testing.T) {
tcp := corev1.ProtocolTCP
udp := corev1.ProtocolUDP
port1 := intstr.FromInt(8080)
port2 := intstr.FromInt(8081)
invalid := intstr.FromString("invalid")
invalidPort := intstr.FromInt(99999)
var (
tcp = corev1.ProtocolTCP
udp = corev1.ProtocolUDP
port1 = int32(8080)
port2 = int32(8081)
invalidPort = int32(99999)
)

tests := []struct {
name string
Ingress []IngressRule
Expand All @@ -35,46 +36,22 @@ func TestPolicySpec_Validate(t *testing.T) {
Except: []string{"192.168.0.1/32"},
},
},
Ports: []networking.NetworkPolicyPort{
Ports: []NetworkPolicyPort{
{
Protocol: nil,
Port: &port1,
Port: port1,
},
{
Protocol: &tcp,
Port: &port2,
Port: port2,
},
{
Protocol: &udp,
Port: &port2,
},
},
},
},
},
{
name: "invalid test",
Ingress: []IngressRule{
{
From: []networking.IPBlock{
{
CIDR: "1.1.0.0/24",
Except: []string{"1.1.1.0/16"},
},
{
CIDR: "192.168.0.1",
Except: []string{"192.168.0.2"},
},
},
Ports: []networking.NetworkPolicyPort{
{
Protocol: nil,
Port: &invalid,
Port: port2,
},
},
},
},
wantErr: true,
},
{
name: "invalid port",
Expand All @@ -85,10 +62,10 @@ func TestPolicySpec_Validate(t *testing.T) {
CIDR: "1.1.0.0/24",
},
},
Ports: []networking.NetworkPolicyPort{
Ports: []NetworkPolicyPort{
{
Protocol: &tcp,
Port: &invalidPort,
Port: invalidPort,
},
},
},
Expand Down
30 changes: 28 additions & 2 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 10 additions & 22 deletions config/crd/bases/metal-stack.io_clusterwidenetworkpolicies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,17 @@ spec:
description: |-
endPort indicates that the range of ports from port to endPort if set, inclusive,
should be allowed by the policy. This field cannot be defined if the port field
is not defined or if the port field is defined as a named (string) port.
is not defined.
The endPort must be equal or greater than port.
format: int32
type: integer
port:
anyOf:
- type: integer
- type: string
description: |-
port represents the port on the given protocol. This can either be a numerical or named
port on a pod. If this field is not provided, this matches all port names and
numbers.
If present, only traffic on the specified protocol AND port will be matched.
x-kubernetes-int-or-string: true
description: port represents the port on the given protocol.
format: int32
type: integer
protocol:
description: |-
protocol represents the protocol (TCP, UDP, or SCTP) which traffic must match.
protocol represents the protocol (TCP, UDP) which traffic must match.
If not specified, this field defaults to TCP.
type: string
type: object
Expand Down Expand Up @@ -213,23 +207,17 @@ spec:
description: |-
endPort indicates that the range of ports from port to endPort if set, inclusive,
should be allowed by the policy. This field cannot be defined if the port field
is not defined or if the port field is defined as a named (string) port.
is not defined.
The endPort must be equal or greater than port.
format: int32
type: integer
port:
anyOf:
- type: integer
- type: string
description: |-
port represents the port on the given protocol. This can either be a numerical or named
port on a pod. If this field is not provided, this matches all port names and
numbers.
If present, only traffic on the specified protocol AND port will be matched.
x-kubernetes-int-or-string: true
description: port represents the port on the given protocol.
format: int32
type: integer
protocol:
description: |-
protocol represents the protocol (TCP, UDP, or SCTP) which traffic must match.
protocol represents the protocol (TCP, UDP) which traffic must match.
If not specified, this field defaults to TCP.
type: string
type: object
Expand Down
16 changes: 13 additions & 3 deletions controllers/firewall_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ func TestConvert(t *testing.T) {
Spec: firewallv1.PolicySpec{
Egress: []firewallv1.EgressRule{
{
Ports: []networking.NetworkPolicyPort{
Ports: []firewallv1.NetworkPolicyPort{
{
Port: &p,
Port: p.IntVal,
Protocol: &tcp,
},
},
Expand Down Expand Up @@ -166,8 +166,18 @@ func convert(np networking.NetworkPolicy) (*firewallv1.ClusterwideNetworkPolicy,
if len(newTos) == 0 {
continue
}

var ports []firewallv1.NetworkPolicyPort
for _, p := range egress.Ports {
ports = append(ports, firewallv1.NetworkPolicyPort{
Protocol: p.Protocol,
Port: p.Port.IntVal,
EndPort: p.EndPort,
})
}

newEgresses = append(newEgresses, firewallv1.EgressRule{
Ports: egress.Ports,
Ports: ports,
To: newTos,
})
}
Expand Down
22 changes: 14 additions & 8 deletions pkg/nftables/networkpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package nftables

import (
"fmt"
"strconv"
"strings"

networkingv1 "k8s.io/api/networking/v1"

firewallv1 "github.com/metal-stack/firewall-controller/v2/api/v1"
)

Expand Down Expand Up @@ -150,19 +149,26 @@ func clusterwideNetworkPolicyEgressToFQDNRules(
return rules, fqdnState
}

func calculatePorts(ports []networkingv1.NetworkPolicyPort) (tcpPorts, udpPorts []string) {
func calculatePorts(ports []firewallv1.NetworkPolicyPort) (tcpPorts, udpPorts []string) {
for _, p := range ports {
proto := proto(p.Protocol)
portStr := fmt.Sprint(p.Port)
var (
proto = proto(p.Protocol)
portStr = strconv.FormatInt(int64(p.Port), 10)
)

if p.EndPort != nil {
portStr = fmt.Sprintf("%s-%d", p.Port, *p.EndPort)
portStr = fmt.Sprintf("%s-%d", portStr, *p.EndPort)
}

switch proto {
case "tcp":
tcpPorts = append(tcpPorts, portStr)
case "udp":
udpPorts = append(udpPorts, portStr)
case "tcp":
fallthrough
default:
tcpPorts = append(tcpPorts, portStr)
}
}

return tcpPorts, udpPorts
}
Loading
Loading