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
78 changes: 69 additions & 9 deletions plugins/modules/ufw.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,18 @@ def ufw_version():

return major, minor, rev

def decode_comment(match):
try:
hexcode = match.group(2)
hexcode = "".join([chr(int(hexcode[h:h + 2], 16)) for h in range(0, len(hexcode), 2)])
return "{0}{1}{2}".format(match.group(1), repr(hexcode), match.group(3))
except Exception as e:
return match.group(0)

params = module.params

commands = {key: params[key] for key in command_keys if params[key]}
commands = dict((key, params[key]) for key in command_keys if params[key])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep the dictionary literal syntax.

diff = None

# Ensure ufw is available
ufw_bin = module.get_bin_path('ufw', True)
Expand All @@ -457,13 +466,16 @@ def ufw_version():
if command == 'state':
states = {'enabled': 'enable', 'disabled': 'disable',
'reloaded': 'reload', 'reset': 'reset'}

if value in ['reloaded', 'reset']:
changed = True

ufw_enabled = pre_state.find(" active") != -1
diff = dict(
before="Status: {}\n".format("enabled" if ufw_enabled else "disabled"),
after="Status: {}\n".format(value),
)
if module.check_mode:
# "active" would also match "inactive", hence the space
ufw_enabled = pre_state.find(" active") != -1
if (value == 'disabled' and ufw_enabled) or (value == 'enabled' and not ufw_enabled):
changed = True
else:
Expand All @@ -472,6 +484,15 @@ def ufw_version():
elif command == 'logging':
extract = re.search(r'Logging: (on|off)(?: \(([a-z]+)\))?', pre_state)
if extract:
diff = dict(
before=extract.group(0),
)
if value == 'off':
diff["after"] = "Logging: off"
elif value == 'on':
diff["after"] = "Logging: on ({})".format(extract.group(2) or "unknown")
else:
diff["after"] = "Logging: on ({})".format(value)
current_level = extract.group(2)
current_on_off_value = extract.group(1)
if value != "off":
Expand All @@ -482,6 +503,15 @@ def ufw_version():
elif current_on_off_value != "off":
changed = True
else:
diff = dict(
before="Logging: Unknown\n",
)
if value == 'off':
diff["after"] = "Logging: off"
elif value == 'on':
diff["after"] = "Logging: on (unknown)"
else:
diff["after"] = "Logging: on ({})".format(value)
changed = True

if not module.check_mode:
Expand All @@ -503,6 +533,11 @@ def ufw_version():
changed = True
else:
changed = True
v = "(unknown)"
diff = dict(
before="{} {}\n".format(params['direction'], v),
after="{} {}\n".format(params['direction'], value),
)
else:
execute(cmd + [[command], [value], [params['direction']]])

Expand Down Expand Up @@ -564,6 +599,15 @@ def ufw_version():
cmd.append([params['comment'], "comment '%s'" % params['comment']])

rules_dry = execute(cmd)
cmd = [[ufw_bin], ["--dry-run route allow in on foo out on bar from 1.1.1.2 port 7000 to 8.8.8.8 port 7001 proto tcp"]]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These hard-coded values look wrong. What is this supposed to do?

remove1 = "### tuple ### route:allow tcp 7001 8.8.8.8 7000 1.1.1.2 in_foo!out_bar\n"
remove2 = "-A ufw-user-forward -i foo -o bar -p tcp -d 8.8.8.8 --dport 7001 -s 1.1.1.2 --sport 7000 -j ACCEPT\n"
diff = dict(
before=execute(cmd).replace(remove1 + remove2, '').replace('\n\n\n', '\n\n'),
after=rules_dry,
)
diff["before"] = re.sub(r"(comment=)([\da-f]+)(\n)", decode_comment, diff["before"])
diff["after"] = re.sub(r"(comment=)([\da-f]+)(\n)", decode_comment, diff["after"])

if module.check_mode:

Expand All @@ -581,16 +625,32 @@ def ufw_version():
changed = True
elif pre_rules != rules_dry:
changed = True
else:
diff = None

if not module.check_mode:
post_state = execute([[ufw_bin], ['status'], ['verbose']])
post_rules = get_current_rules()
if (not changed):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (not changed):
if not changed:

diff = dict(
before="{}\n\n---\n\n{}".format(pre_state, pre_rules),
after="{}\n\n---\n\n{}".format(post_state, post_rules),
)
changed = (pre_state != post_state) or (pre_rules != post_rules)

if (diff is not None) and (diff["before"] == diff["after"]):
diff = None

if (changed) and (diff is None):
raise Exception("ufw module reported a change, but no differences detected")
elif (changed is False) and (diff is not None):
Comment on lines +641 to +646
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unusual to use these many brackets in Python:

Suggested change
if (diff is not None) and (diff["before"] == diff["after"]):
diff = None
if (changed) and (diff is None):
raise Exception("ufw module reported a change, but no differences detected")
elif (changed is False) and (diff is not None):
if diff is not None and diff["before"] == diff["after"]:
diff = None
if changed and diff is None:
raise Exception("ufw module reported a change, but no differences detected")
elif changed is False and diff is not None:

raise Exception("ufw module reported no change, but differences were detcted", diff, cmds)

# Get the new state
if module.check_mode:
return module.exit_json(changed=changed, commands=cmds)
return module.exit_json(changed=changed, commands=cmds, diff=diff)
else:
post_state = execute([[ufw_bin], ['status'], ['verbose']])
if not changed:
post_rules = get_current_rules()
changed = (pre_state != post_state) or (pre_rules != post_rules)
return module.exit_json(changed=changed, commands=cmds, msg=post_state.rstrip())
return module.exit_json(changed=changed, commands=cmds, msg=post_state.rstrip(), diff=diff)


if __name__ == '__main__':
Expand Down
1 change: 1 addition & 0 deletions tests/unit/plugins/modules/test_ufw.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"ufw --dry-run insert 1 allow from any to any port 7000 proto tcp": skippg_adding_existing_rules,
"ufw --dry-run delete allow from any to any port 7000 proto tcp": "",
"ufw --dry-run delete allow from any to any port 7001 proto tcp": user_rules_with_port_7000,
"ufw --dry-run route allow in on foo out on bar from 1.1.1.2 port 7000 to 8.8.8.8 port 7001 proto tcp": "",
"ufw --dry-run route allow in on foo out on bar from 1.1.1.1 port 7000 to 8.8.8.8 port 7001 proto tcp": "",
"ufw --dry-run allow in on foo from any to any port 7003 proto tcp": "",
"ufw --dry-run allow in on foo from 1.1.1.1 port 7002 to 8.8.8.8 port 7003 proto tcp": "",
Expand Down
Loading