Commit 3ca92b51 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Tests - Tools - Firewall Agent:

- Added missing firewall Table types
- Enhanced NFT parser to skip additional unknown rules
- Enhanced command executor to skip changes on pre-existing rules
- Added deployability as Kubernetes workload
parent 51fb0c51
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
# Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# 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.


apiVersion: apps/v1
kind: Deployment
metadata:
  name: firewall-agent
spec:
  replicas: 1
  selector:
    matchLabels:
      app: firewall-agent
  template:
    metadata:
      labels:
        app: firewall-agent
    spec:
      hostNetwork: true               # like --network host
      dnsPolicy: ClusterFirstWithHostNet
      containers:
        - name: firewall-agent
          image: firewall-agent:dev
          #image: localhost:32000/tfs/firewall-agent:dev
          securityContext:
            capabilities:
              add: ["NET_ADMIN"]      # like --cap-add=NET_ADMIN
            # privileged: true        # uncomment if your code needs full net admin / sysctl
          ports:
            - containerPort: 8888     # container listens on 8888 on the host now
              hostPort: 8888          # optional, but makes it explicit
+9 −2
Original line number Diff line number Diff line
@@ -117,12 +117,15 @@ class Chain:

    def get_commands(self, removal : bool = False) -> List[Tuple[int, str]]:
        commands : List[Tuple[int, str]] = list()

        if removal:
            # NOTE: For now, do not remove chains. We do not process all kinds of
            # chains and their removal might cause side effects on NFTables.
            pass
        elif self.handle is not None:
            # NOTE: Chain was already there, do not modify it
            pass
        else:
            chain_hook = str(self.chain).lower()
            parts = [
                'add', 'chain', self.family.value, self.table.value, self.chain,
                '{',
@@ -131,6 +134,10 @@ class Chain:
                '}'
            ]
            commands.append((-1, ' '.join(parts)))

        for rule in self.rules:
            commands.append(rule.get_command(removal=removal))
            rule_cmd = rule.get_command(removal=removal)
            if rule_cmd is None: continue
            commands.append(rule_cmd)

        return commands
+3 −0
Original line number Diff line number Diff line
@@ -81,6 +81,9 @@ def parse_nft_match(rule : 'Rule', match : Dict) -> int:
                raise UnsupportedElementException('rule.expr.match', match)
        else:
            raise UnsupportedElementException('rule.expr.match', match)
    elif '&' in match_left:
        # matches on masks and marks are skipped
        pass
    else:
        raise UnsupportedElementException('rule.expr.match', match)

+6 −2
Original line number Diff line number Diff line
@@ -252,7 +252,7 @@ class Rule:
        if self.handle is not None: rule['handle'] = self.handle
        return [{'rule': rule}]

    def get_command(self, removal : bool = False) -> Tuple[int, str]:
    def get_command(self, removal : bool = False) -> Optional[Tuple[int, str]]:
        if removal:
            if self.handle is None: raise MissingFieldException('handle', asdict(self))
            parts = [
@@ -260,6 +260,10 @@ class Rule:
                self.family.value, self.table.value, self.chain,
                'handle', str(self.handle)
            ]
            return self.sequence_id, ' '.join(parts)
        elif self.handle is not None:
            # NOTE: Rule was already there, do not modify it
            return None
        else:
            # NOTE: if sequence_id < 10000: insert the rules to the top;
            # otherwise, append to the bottom. Anyways, sort rules by sequence_id.
+6 −0
Original line number Diff line number Diff line
@@ -78,13 +78,19 @@ class Table:

    def get_commands(self, removal : bool = False) -> List[Tuple[int, str]]:
        commands : List[Tuple[int, str]] = list()

        if removal:
            # NOTE: For now, do not remove tables. We do not process all kinds of
            # tables and their removal might cause side effects on NFTables.
            pass
        elif self.handle is not None:
            # NOTE: Table was already there, do not modify it
            pass
        else:
            parts = ['add', 'table', self.family.value, self.table.value]
            commands.append((-2, ' '.join(parts)))

        for chain in self.chains.values():
            commands.extend(chain.get_commands(removal=removal))

        return commands
Loading