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