Saltstack Official UFW Formula
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
5.0KB

  1. from salt.exceptions import CommandExecutionError, CommandNotFoundError
  2. import re
  3. import socket
  4. def _unchanged(name, msg):
  5. return {'name': name, 'result': True, 'comment': msg, 'changes': {}}
  6. def _test(name, msg):
  7. return {'name': name, 'result': None, 'comment': msg, 'changes': {}}
  8. def _error(name, msg):
  9. return {'name': name, 'result': False, 'comment': msg, 'changes': {}}
  10. def _changed(name, msg, **changes):
  11. return {'name': name, 'result': True, 'comment': msg, 'changes': changes}
  12. def _resolve(host):
  13. # let's just see if it starts with a number or a colon, for simplicity
  14. if re.match(r'^[0-9:]', host):
  15. return host
  16. return socket.gethostbyname(host)
  17. def _as_rule(method, app, interface, protocol, from_addr, from_port, to_addr, to_port, comment):
  18. cmd = [method]
  19. if app is not None:
  20. cmd.append("from")
  21. if from_addr is not None:
  22. cmd.append(from_addr)
  23. else:
  24. cmd.append("any")
  25. cmd.append("to")
  26. if to_addr is not None:
  27. cmd.append(to_addr)
  28. else:
  29. cmd.append("any")
  30. cmd.append("app")
  31. cmd.append(app)
  32. elif interface is not None:
  33. cmd.append("in")
  34. cmd.append("on")
  35. cmd.append(interface)
  36. else:
  37. if protocol is not None:
  38. cmd.append("proto")
  39. cmd.append(protocol)
  40. cmd.append("from")
  41. if from_addr is not None:
  42. cmd.append(_resolve(from_addr))
  43. else:
  44. cmd.append("any")
  45. if from_port is not None:
  46. cmd.append("port")
  47. cmd.append(_resolve(from_port))
  48. cmd.append("to")
  49. if to_addr is not None:
  50. cmd.append(to_addr)
  51. else:
  52. cmd.append("any")
  53. if to_port is not None:
  54. cmd.append("port")
  55. cmd.append(to_port)
  56. if comment is not None:
  57. cmd.append("comment")
  58. cmd.append(comment)
  59. real_cmd = ' '.join(cmd)
  60. return real_cmd
  61. def enabled(name, **kwargs):
  62. if __salt__['ufw.is_enabled']():
  63. return _unchanged(name, "UFW is already enabled")
  64. if __opts__['test']:
  65. return _test(name, "UFW will be enabled")
  66. try:
  67. __salt__['ufw.set_enabled'](True)
  68. except (CommandExecutionError, CommandNotFoundError) as e:
  69. return _error(name, e.message)
  70. return _changed(name, "UFW is enabled", enabled=True)
  71. def default_incoming(name, default):
  72. rule = "default {0} incoming".format(default)
  73. if __opts__['test']:
  74. return _test(name, "{0}: {1}".format(name, rule))
  75. current = __salt__['ufw.get_default_incoming']()
  76. if default != current:
  77. try:
  78. out = __salt__['ufw.add_rule'](rule)
  79. except (CommandExecutionError, CommandNotFoundError) as e:
  80. return _error(name, e.message)
  81. for line in out.split('\n'):
  82. if line.startswith("Default incoming policy changed to"):
  83. return _changed(name, "{0} set to {1}".format(name, default), rule=rule)
  84. return _error(name, line)
  85. return _unchanged(name, "{0} was already set to {1}".format(name, default))
  86. def default_outgoing(name, default):
  87. rule = "default {0} outgoing".format(default)
  88. if __opts__['test']:
  89. return _test(name, "{0}: {1}".format(name, rule))
  90. current = __salt__['ufw.get_default_outgoing']()
  91. if default != current:
  92. try:
  93. out = __salt__['ufw.add_rule'](rule)
  94. except (CommandExecutionError, CommandNotFoundError) as e:
  95. return _error(name, e.message)
  96. for line in out.split('\n'):
  97. if line.startswith("Default outgoing policy changed to"):
  98. return _changed(name, "{0} set to {1}".format(name, default), rule=rule)
  99. return _error(name, line)
  100. return _unchanged(name, "{0} was already set to {1}".format(name, default))
  101. def allowed(name, app=None, interface=None, protocol=None,
  102. from_addr=None, from_port=None, to_addr=None, to_port=None, comment=None):
  103. rule = _as_rule("allow", app=app, interface=interface, protocol=protocol,
  104. from_addr=from_addr, from_port=from_port, to_addr=to_addr, to_port=to_port, comment=comment)
  105. try:
  106. out = __salt__['ufw.add_rule'](rule)
  107. except (CommandExecutionError, CommandNotFoundError) as e:
  108. return _error(name, e.message)
  109. changes = False
  110. for line in out.split('\n'):
  111. if line.startswith("Skipping"):
  112. if __opts__['test']:
  113. return _unchanged(name, "{0} was already allowed".format(name))
  114. break
  115. else:
  116. continue
  117. if line.startswith("Rule added") or line.startswith("Rules updated"):
  118. changes = True
  119. break
  120. if __opts__['test']:
  121. return _test(name, "{0} would have been allowed".format(name))
  122. break
  123. return _error(name, line)
  124. if changes:
  125. return _changed(name, "{0} allowed".format(name), rule=rule)
  126. else:
  127. return _unchanged(name, "{0} was already allowed".format(name))