Skip to content

Commit

Permalink
Network: firewall controller chain
Browse files Browse the repository at this point in the history
  • Loading branch information
cheina97 committed Nov 17, 2023
1 parent c35ff41 commit a599696
Show file tree
Hide file tree
Showing 16 changed files with 532 additions and 13 deletions.
13 changes: 7 additions & 6 deletions apis/networking/v1alpha1/firewall/chain_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,20 @@ var (
// +kubebuilder:object:generate=true
type Chain struct {
// Name is the name of the chain.
Name string `json:"name,omitempty"`
Name string `json:"name"`
// Rules is a list of rules to be applied to the chain.
Rules RulesSet `json:"rules,omitempty"`
Rules RulesSet `json:"rules"`
// Type defines what this chain will be used for.
// +kubebuilder:validation:Enum="filter";"route";"nat"
Type ChainType `json:"type,omitempty"`
Type ChainType `json:"type"`
// Policy defines what this chain default policy will be.
// +kubebuilder:validation:Enum="drop";"accept"
Policy ChainPolicy `json:"policy,omitempty"`
// +kubebuilder:validation:Optional
Policy ChainPolicy `json:"policy"`
// Hook specifies at which step in packet processing the Chain should be executed.
// +kubebuilder:validation:Enum="prerouting";"input";"forward";"output";"postrouting";"ingress"
Hook ChainHook `json:"hook,omitempty"`
Hook ChainHook `json:"hook"`
// Priority orders the chain relative to Netfilter internal operations.
// +kubebuilder:default=0
Priority ChainPriority `json:"priority,omitempty"`
Priority ChainPriority `json:"priority"`
}
9 changes: 6 additions & 3 deletions apis/networking/v1alpha1/firewall/rules_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ type RouteRule struct {
// +kubebuilder:object:generate=true
type RulesSet struct {
// NatRules is a list of rules to be applied to the chain.
NatRules []NatRule `json:"natRules,omitempty"`
// +kubebuilder:validation:Optional
NatRules []NatRule `json:"natRules"`
// FilterRules is a list of rules to be applied to the chain.
FilterRules []FilterRule `json:"filterRules,omitempty"`
// +kubebuilder:validation:Optional
FilterRules []FilterRule `json:"filterRules"`
// RouteRules is a list of rules to be applied to the chain.
RouteRules []RouteRule `json:"routeRules,omitempty"`
// +kubebuilder:validation:Optional
RouteRules []RouteRule `json:"routeRules"`
}
7 changes: 4 additions & 3 deletions apis/networking/v1alpha1/firewall/table_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ const (
// +kubebuilder:object:generate=true
type Table struct {
// Name is the name of the table.
Name string `json:"name,omitempty"`
Name string `json:"name"`
// Chains is a list of chains to be applied to the table.
Chains []Chain `json:"chains,omitempty"`
// +kubebuilder:validation:Optional
Chains []Chain `json:"chains"`
// Family is the family of the table.
// +kubebuilder:validation:Enum="INET";"IPV4";"IPV6";"ARP";"NETDEV";"BRIDGE"
Family TableFamily `json:"family,omitempty"`
Family TableFamily `json:"family"`
}
2 changes: 1 addition & 1 deletion apis/networking/v1alpha1/firewallconfiguration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
// FirewallConfigurationSpec defines the desired state of FirewallConfiguration.
type FirewallConfigurationSpec struct {
// Table contains the rules to be applied to the firewall.
Table firewallapi.Table `json:"table,omitempty"`
Table firewallapi.Table `json:"table"`
}

// FirewallConfigurationStatusCondition defines the observed state of FirewallConfiguration.
Expand Down
2 changes: 2 additions & 0 deletions cmd/liqo-controller-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import (
virtualkubeletv1alpha1 "github.com/liqotech/liqo/apis/virtualkubelet/v1alpha1"
"github.com/liqotech/liqo/cmd/virtual-kubelet/root"
"github.com/liqotech/liqo/pkg/consts"
firewall "github.com/liqotech/liqo/pkg/firewall/webhooks"
identitymanager "github.com/liqotech/liqo/pkg/identityManager"
clientoperator "github.com/liqotech/liqo/pkg/liqo-controller-manager/external-network/client-operator"
configurationcontroller "github.com/liqotech/liqo/pkg/liqo-controller-manager/external-network/configuration-controller"
Expand Down Expand Up @@ -430,6 +431,7 @@ func main() {
mgr.GetWebhookServer().Register("/mutate/virtualnodes", virtualnodewh.New(mgr.GetClient(), &clusterIdentity, virtualKubeletOpts))
mgr.GetWebhookServer().Register("/validate/networks", nwwh.NewValidator())
mgr.GetWebhookServer().Register("/validate/ips", ipwh.NewValidator())
mgr.GetWebhookServer().Register("/validate/firewallconfigurations", firewall.NewValidator())

if err := indexer.IndexField(ctx, mgr, &corev1.Pod{}, indexer.FieldNodeNameFromPod, indexer.ExtractNodeName); err != nil {
klog.Errorf("Unable to setup the indexer for the Pod nodeName field: %v", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ spec:
- route
- nat
type: string
required:
- hook
- name
- priority
- rules
- type
type: object
type: array
family:
Expand All @@ -123,7 +129,12 @@ spec:
name:
description: Name is the name of the table.
type: string
required:
- family
- name
type: object
required:
- table
type: object
status:
description: FirewallConfigurationStatus defines the observed state of
Expand Down
17 changes: 17 additions & 0 deletions deployments/liqo/templates/webhooks/liqo-validating-webhook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,21 @@ webhooks:
apiVersions: ["v1alpha1"]
resources: ["ips"]
sideEffects: None
failurePolicy: {{ .Values.webhook.failurePolicy }}
- name: firewallconfiguration.validate.liqo.io
admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: {{ include "liqo.prefixedName" $ctrlManagerConfig }}
namespace: {{ .Release.Namespace }}
path: "/validate/firewallconfigurations"
port: {{ .Values.webhook.port }}
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["networking.liqo.io"]
apiVersions: ["v1alpha1"]
resources: ["firewallconfigurations"]
sideEffects: None
failurePolicy: {{ .Values.webhook.failurePolicy }}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/containernetworking/plugins v1.3.0
github.com/coreos/go-iptables v0.7.0
github.com/go-git/go-git/v5 v5.10.0
github.com/google/nftables v0.1.0
github.com/google/uuid v1.4.0
github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e
github.com/grandcat/zeroconf v1.0.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,8 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/nftables v0.1.0 h1:T6lS4qudrMufcNIZ8wSRrL+iuwhsKxpN+zFLxhUWOqk=
github.com/google/nftables v0.1.0/go.mod h1:b97ulCCFipUC+kSin+zygkvUVpx0vyIAwxXFdY3PlNc=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
Expand Down
107 changes: 107 additions & 0 deletions pkg/firewall/chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2019-2023 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package firewall

import (
"github.com/google/nftables"

firewallapi "github.com/liqotech/liqo/apis/networking/v1alpha1/firewall"
)

func addChain(nftconn *nftables.Conn, chain *firewallapi.Chain, table *nftables.Table) {
nftChain := &nftables.Chain{Table: table}
setChainName(nftChain, chain.Name)
setHooknum(nftChain, chain.Hook)
setPriority(nftChain, chain.Priority)
setType(nftChain, chain.Type)
setPolicy(nftChain, chain.Policy)
nftconn.AddChain(nftChain)
}

func setChainName(chain *nftables.Chain, name string) {
chain.Name = name
}

func setHooknum(chain *nftables.Chain, hooknum firewallapi.ChainHook) {
switch hooknum {
case firewallapi.ChainHookPrerouting:
chain.Hooknum = nftables.ChainHookPrerouting
case firewallapi.ChainHookInput:
chain.Hooknum = nftables.ChainHookInput
case firewallapi.ChainHookForward:
chain.Hooknum = nftables.ChainHookForward
case firewallapi.ChainHookOutput:
chain.Hooknum = nftables.ChainHookOutput
case firewallapi.ChainHookPostrouting:
chain.Hooknum = nftables.ChainHookPostrouting
case firewallapi.ChainHookIngress:
chain.Hooknum = nftables.ChainHookIngress
}
}

func setPriority(chain *nftables.Chain, priority firewallapi.ChainPriority) {
switch priority {
case firewallapi.ChainPriorityFirst:
chain.Priority = nftables.ChainPriorityFirst
case firewallapi.ChainPriorityConntrackDefrag:
chain.Priority = nftables.ChainPriorityConntrackDefrag
case firewallapi.ChainPriorityRaw:
chain.Priority = nftables.ChainPriorityRaw
case firewallapi.ChainPrioritySELinuxFirst:
chain.Priority = nftables.ChainPrioritySELinuxFirst
case firewallapi.ChainPriorityConntrack:
chain.Priority = nftables.ChainPriorityConntrack
case firewallapi.ChainPriorityMangle:
chain.Priority = nftables.ChainPriorityMangle
case firewallapi.ChainPriorityNATDest:
chain.Priority = nftables.ChainPriorityNATDest
case firewallapi.ChainPriorityFilter:
chain.Priority = nftables.ChainPriorityFilter
case firewallapi.ChainPrioritySecurity:
chain.Priority = nftables.ChainPrioritySecurity
case firewallapi.ChainPriorityNATSource:
chain.Priority = nftables.ChainPriorityNATSource
case firewallapi.ChainPrioritySELinuxLast:
chain.Priority = nftables.ChainPrioritySELinuxLast
case firewallapi.ChainPriorityConntrackHelper:
chain.Priority = nftables.ChainPriorityConntrackHelper
case firewallapi.ChainPriorityConntrackConfirm:
chain.Priority = nftables.ChainPriorityConntrackConfirm
case firewallapi.ChainPriorityLast:
chain.Priority = nftables.ChainPriorityLast
}
}

func setType(chain *nftables.Chain, chainType firewallapi.ChainType) {
switch chainType {
case firewallapi.ChainTypeFilter:
chain.Type = nftables.ChainTypeFilter
case firewallapi.ChainTypeRoute:
chain.Type = nftables.ChainTypeRoute
case firewallapi.ChainTypeNAT:
chain.Type = nftables.ChainTypeNAT
}
}

func setPolicy(chain *nftables.Chain, policy firewallapi.ChainPolicy) {
switch policy {
case firewallapi.ChainPolicyDrop:
p := nftables.ChainPolicyDrop
chain.Policy = &p
case firewallapi.ChainPolicyAccept:
p := nftables.ChainPolicyAccept
chain.Policy = &p
}
}
16 changes: 16 additions & 0 deletions pkg/firewall/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2019-2023 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package firewall contains the controller that manages the firewall configuration.
package firewall
40 changes: 40 additions & 0 deletions pkg/firewall/finalizer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2019-2023 The Liqo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package firewall

import (
"context"

ctrlutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1"
)

const (
// firewallConfigurationsControllerFinalizer is the finalizer added to virtual-node to allow the controller to clean up.
firewallConfigurationsControllerFinalizer = "firewallconfigurations-controller.liqo.io/finalizer"
)

func (r *FirewallConfigurationReconciler) ensureFirewallConfigurationFinalizerPresence(
ctx context.Context, fwcfg *networkingv1alpha1.FirewallConfiguration) error {
ctrlutil.AddFinalizer(fwcfg, firewallConfigurationsControllerFinalizer)
return r.Client.Update(ctx, fwcfg)
}

func (r *FirewallConfigurationReconciler) ensureFirewallConfigurationFinalizerAbsence(
ctx context.Context, fwcfg *networkingv1alpha1.FirewallConfiguration) error {
ctrlutil.RemoveFinalizer(fwcfg, firewallConfigurationsControllerFinalizer)
return r.Client.Update(ctx, fwcfg)
}
Loading

0 comments on commit a599696

Please sign in to comment.