def check()

in azurelinuxagent/ga/firewall_manager.py [0:0]


    def check(self):
        #
        # First check that the walinuxagent table exists.
        #
        # The output of the list command is similar to (see 'man libnftables-json' for details):
        #
        #   {
        #     "nftables": [
        #         { "metainfo": { "version": "1.0.2", "release_name": "Lester Gooch", "json_schema_version": 1 } },
        #         { "table": { "family": "ip", "name": "walinuxagent", "handle": 2 } }
        #     ]
        #   }
        #
        output_text = shellutil.run_command(["nft", "--json",  "list", "tables"])
        try:
            output = json.loads(output_text)
            tables = [i["table"] for i in output["nftables"] if i.get("table") is not None]
            if all(t["name"] != "walinuxagent" for t in tables):
                return False
        except Exception as exception:
            raise Exception("Can't parse the output of 'nft list tables'\n{0}\nERROR: {1}".format(output_text, exception))

        #
        # Now check that the firewall rule is set up correctly.
        #
        # The output of the list command is similar to (see 'man libnftables-json' for details):
        #
        #   {
        #     "nftables": [
        #       { "metainfo": { "version": "1.0.2", "release_name": "Lester Gooch", "json_schema_version": 1 } },
        #       { "table": { "family": "ip", "name": "walinuxagent", "handle": 2 } },
        #       { "chain": { "family": "ip", "table": "walinuxagent", "name": "output", "handle": 1, "type": "filter", "hook": "output", "prio": 0, "policy": "accept" } },
        #       {
        #         "rule": {
        #           "family": "ip", "table": "walinuxagent", "chain": "output", "handle": 2,
        #           "expr": [
        #             { "match": {
        #                 "op": "==",
        #                 "left": {  "payload": { "protocol": "ip", "field": "daddr" } },
        #                 "right": "168.63.129.16"
        #               }},
        #             { "match": {
        #                 "op": "!=",
        #                 "left": { "payload": { "protocol": "tcp", "field": "dport" } },
        #                 "right": 53
        #               }},
        #             { "match": {
        #                 "op": "!=",
        #                 "left": { "meta": { "key": "skuid" } },
        #                 "right": 0
        #               }},
        #             { "match": {
        #                 "op": "in",
        #                 "left": { "ct": { "key": "state" } },
        #                 "right": [ "invalid", "new" ]
        #               }},
        #             { "counter": {
        #                 "packets": 0,
        #                 "bytes": 0
        #               }},
        #             { "drop": null }
        #          ]
        #         }
        #       }
        #     ]
        #   }
        #
        output_text = shellutil.run_command(["nft", "--json",  "list", "table", "walinuxagent"])
        errors = []

        try:
            output = json.loads(output_text)

            rules = [i["rule"] for i in output["nftables"] if i.get("rule") is not None]
            if len(rules) != 1:
                raise FirewallStateError("There should be exactly one rule in the 'output' chain")
            for r in rules:
                if r["table"] == "walinuxagent" and r["family"] == "ip" and r["chain"] == "output":
                    expr = r["expr"]
                    break
            else:
                raise FirewallStateError("Cannot find any rules for the 'output' chain")

            address_match = {"match": {"op": "==", "left": {"payload": {"protocol": "ip", "field": "daddr"}}, "right": self._wire_server_address}}
            if all(i != address_match for i in expr):
                errors.append("No expression matches the WireServer address")

            dns_match = {"match": {"op": "!=", "left": {"payload": {"protocol": "tcp", "field": "dport"}}, "right": 53}}
            if all(i != dns_match for i in expr):
                errors.append("No expression excludes the DNS port")

            owner_expr = {"match": {"op": "!=", "left": {"meta": {"key": "skuid"}}, "right": os.getuid()}}
            if all(i != owner_expr for i in expr):
                errors.append("No expression excludes the Agent's UID")

            drop_action = {"drop": None}
            if all(i != drop_action for i in expr):
                errors.append("The drop action is missing")

        except FirewallStateError:
            raise
        except Exception as exception:
            raise Exception("Can't parse the output of 'nft list table walinuxagent'\n{0}\nERROR: {1}".format(output_text, exception))

        if len(errors) > 0:
            raise FirewallStateError("{0}".format(errors))

        return True