-
-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[COOK-4140] Only notify when a rule is actually added
Signed-off-by: Sean OMeara <[email protected]>
- Loading branch information
Showing
1 changed file
with
101 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,23 +18,39 @@ | |
# limitations under the License. | ||
# | ||
|
||
def whyrun_supported? | ||
true | ||
end | ||
|
||
include Chef::Mixin::ShellOut | ||
|
||
action :allow do | ||
converge_by("Allowing #{new_resource.source} firewall_rule") do | ||
apply_rule('allow') | ||
if rule_exists? | ||
Chef::Log.debug "Rule #{rule} already allowed - skipping" | ||
else | ||
converge_by("Allowing #{rule}") do | ||
apply_rule('allow') | ||
end | ||
end | ||
end | ||
|
||
action :deny do | ||
converge_by("Denying #{new_resource.source} firewall_rule") do | ||
apply_rule('deny') | ||
if rule_exists? | ||
Chef::Log.debug "Rule #{rule} already denied - skipping" | ||
else | ||
converge_by("Denying #{rule}") do | ||
apply_rule('deny') | ||
end | ||
end | ||
end | ||
|
||
action :reject do | ||
converge_by("Rejecting #{new_resource.source} firewall_rule") do | ||
apply_rule('reject') | ||
if rule_exists? | ||
Chef::Log.debug "Rule #{rule} already rejected - skipping" | ||
else | ||
converge_by("Rejecting #{rule}") do | ||
apply_rule('reject') | ||
end | ||
end | ||
end | ||
|
||
|
@@ -43,48 +59,17 @@ | |
# ufw deny proto tcp from 10.0.0.0/8 to 192.168.0.1 port 25 | ||
# ufw insert 1 allow proto tcp from 0.0.0.0/0 to 192.168.0.1 port 25 | ||
def apply_rule(type = nil) # rubocop:disable MethodLength | ||
if rule_exists? | ||
Chef::Log.debug("#{@new_resource} #{type} rule exists..skipping.") | ||
else | ||
ufw_command = 'ufw ' | ||
ufw_command << "insert #{@new_resource.position} " if @new_resource.position | ||
ufw_command << "#{type} " | ||
ufw_command << "#{@new_resource.direction} " if @new_resource.direction | ||
if @new_resource.interface | ||
if @new_resource.direction | ||
ufw_command << "on #{@new_resource.interface} " | ||
else | ||
ufw_command << "in on #{@new_resource.interface} " | ||
end | ||
end | ||
ufw_command << logging | ||
ufw_command << "proto #{@new_resource.protocol} " if @new_resource.protocol | ||
if @new_resource.source | ||
ufw_command << "from #{@new_resource.source} " | ||
else | ||
ufw_command << 'from any ' | ||
end | ||
ufw_command << "port #{@new_resource.dest_port} " if @new_resource.dest_port | ||
if @new_resource.destination | ||
ufw_command << "to #{@new_resource.destination} " | ||
else | ||
ufw_command << 'to any ' | ||
end | ||
if @new_resource.port | ||
ufw_command << "port #{@new_resource.port} " | ||
elsif @new_resource.ports | ||
ufw_command << "port #{@new_resource.ports.join(',')} " | ||
elsif @new_resource.port_range | ||
ufw_command << "port #{@new_resource.port_range.first}:#{@new_resource.port_range.last} " | ||
end | ||
ufw_command = 'ufw ' | ||
ufw_command << "insert #{@new_resource.position} " if @new_resource.position | ||
ufw_command << "#{type} " | ||
ufw_command << "#{rule} " | ||
|
||
Chef::Log.debug("ufw: #{ufw_command}") | ||
shell_out!(ufw_command) | ||
Chef::Log.debug("ufw: #{ufw_command}") | ||
shell_out!(ufw_command) | ||
|
||
Chef::Log.info("#{@new_resource} #{type} rule added") | ||
shell_out!('ufw status verbose') # purely for the Chef::Log.debug output | ||
new_resource.updated_by_last_action(true) | ||
end | ||
Chef::Log.info("#{@new_resource} #{type} rule added") | ||
shell_out!('ufw status verbose') # purely for the Chef::Log.debug output | ||
new_resource.updated_by_last_action(true) | ||
end | ||
|
||
def logging | ||
|
@@ -98,8 +83,37 @@ def logging | |
end | ||
end | ||
|
||
def port_and_proto | ||
@new_resource.protocol ? "#{@new_resource.port}/#{@new_resource.protocol}" : @new_resource.port | ||
def rule | ||
rule = '' | ||
rule << "#{@new_resource.direction} " if @new_resource.direction | ||
if @new_resource.interface | ||
if @new_resource.direction | ||
rule << "on #{@new_resource.interface} " | ||
else | ||
rule << "in on #{@new_resource.interface} " | ||
end | ||
end | ||
rule << logging | ||
rule << "proto #{@new_resource.protocol} " if @new_resource.protocol | ||
if @new_resource.source | ||
rule << "from #{@new_resource.source} " | ||
else | ||
rule << 'from any ' | ||
end | ||
rule << "port #{@new_resource.dest_port} " if @new_resource.dest_port | ||
if @new_resource.destination | ||
rule << "to #{@new_resource.destination} " | ||
else | ||
rule << 'to any ' | ||
end | ||
if @new_resource.port | ||
rule << "port #{@new_resource.port} " | ||
elsif @new_resource.ports | ||
rule << "port #{@new_resource.ports.join(',')} " | ||
elsif @new_resource.port_range | ||
rule << "port #{@new_resource.port_range.first}:#{@new_resource.port_range.last} " | ||
end | ||
rule.strip | ||
end | ||
|
||
# TODO: currently only works when firewall is enabled | ||
|
@@ -108,5 +122,43 @@ def rule_exists? | |
# -- ------ ---- | ||
# 22 ALLOW Anywhere | ||
# 192.168.0.1 25/tcp DENY 10.0.0.0/8 | ||
shell_out!('ufw status').stdout =~ /^(#{@new_resource.destination}\s)?#{port_and_proto}\s.*(#{@new_resource.action.to_s})\s.*#{@new_resource.source || 'Anywhere'}$/i | ||
# 22 ALLOW Anywhere | ||
# 3309 on eth9 ALLOW Anywhere | ||
# Anywhere ALLOW Anywhere | ||
# 80 ALLOW Anywhere (log) | ||
# 8080 DENY 192.168.1.0/24 | ||
# 1.2.3.5 5469/udp ALLOW 1.2.3.4 5469/udp | ||
# 3308 ALLOW OUT Anywhere on eth8 | ||
|
||
to = '' | ||
if @new_resource.destination | ||
to << "#{Regexp.escape(@new_resource.destination)}\s" | ||
end | ||
if @new_resource.protocol && @new_resource.port | ||
to << "#{Regexp.escape("#{@new_resource.port}/#{@new_resource.protocol}")}\s" | ||
elsif @new_resource.port | ||
to << "#{Regexp.escape(@new_resource.port)}\s" | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
someara
|
||
end | ||
if to.empty? | ||
to << "Anywhere\s" | ||
end | ||
|
||
action = @new_resource.action | ||
action = action.first if action.is_a?(Enumerable) | ||
action = "#{Regexp.escape(action.to_s.upcase)}\s" | ||
|
||
from = '' | ||
from << "#{Regexp.escape(@new_resource.source || 'Anywhere')}" | ||
|
||
regex = /^#{to}.*#{action}.*#{from}.*$/ | ||
|
||
match = shell_out!('ufw status').stdout.lines.find do |line| | ||
# TODO: support IPv6 | ||
return false if line =~ /\(v6\)$/ | ||
line =~ regex | ||
end | ||
|
||
Chef::Log.debug("ufw: found existing rule for \"#{rule}\": \"#{match.strip}\"") if match | ||
|
||
!!match | ||
end |
This is plain busted.
The resource defines
port
as such:Passing a Fixnum to
Regexp.escape()
throws an exception. This should be re-written like so: