dust-deploy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +154 -0
- data/Rakefile +1 -0
- data/bin/dust +215 -0
- data/dust.gemspec +28 -0
- data/lib/dust.rb +6 -0
- data/lib/dust/convert_size.rb +21 -0
- data/lib/dust/print_status.rb +57 -0
- data/lib/dust/recipes/aliases.rb +13 -0
- data/lib/dust/recipes/basic_setup.rb +35 -0
- data/lib/dust/recipes/debsecan.rb +44 -0
- data/lib/dust/recipes/duplicity.rb +111 -0
- data/lib/dust/recipes/etc_hosts.rb +13 -0
- data/lib/dust/recipes/iptables.rb +267 -0
- data/lib/dust/recipes/locale.rb +17 -0
- data/lib/dust/recipes/memory_limit.rb +23 -0
- data/lib/dust/recipes/motd.rb +12 -0
- data/lib/dust/recipes/mysql.rb +49 -0
- data/lib/dust/recipes/nginx.rb +53 -0
- data/lib/dust/recipes/packages.rb +9 -0
- data/lib/dust/recipes/postgres.rb +119 -0
- data/lib/dust/recipes/rc_local.rb +24 -0
- data/lib/dust/recipes/repositories.rb +88 -0
- data/lib/dust/recipes/resolv_conf.rb +42 -0
- data/lib/dust/recipes/ssh_authorized_keys.rb +58 -0
- data/lib/dust/recipes/unattended_upgrades.rb +29 -0
- data/lib/dust/recipes/zabbix_agent.rb +84 -0
- data/lib/dust/server.rb +382 -0
- data/lib/dust/version.rb +3 -0
- metadata +139 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
class Aliases < Thor
|
2
|
+
desc 'aliases:deploy', 'installs email aliases'
|
3
|
+
def deploy node, ingredients
|
4
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
5
|
+
|
6
|
+
return unless node.package_installed? 'postfix'
|
7
|
+
node.scp "#{template_path}/aliases", '/etc/aliases'
|
8
|
+
|
9
|
+
::Dust.print_msg 'running newaliases', 1
|
10
|
+
::Dust.print_result node.exec('newaliases')[:exit_code]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class BasicSetup < Thor
|
2
|
+
desc 'basic_setup:deploy', 'installs basic packages and config files'
|
3
|
+
def deploy node, ingredients, options
|
4
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
5
|
+
|
6
|
+
# install some basic packages
|
7
|
+
::Dust.print_msg "installing basic packages\n"
|
8
|
+
|
9
|
+
node.install_package 'screen', false, 2
|
10
|
+
node.install_package 'rsync', false, 2
|
11
|
+
node.install_package 'psmisc', false, 2 if node.uses_apt? true
|
12
|
+
|
13
|
+
if node.uses_rpm? true
|
14
|
+
node.install_package 'vim-enhanced', false, 2
|
15
|
+
else
|
16
|
+
node.install_package 'vim', false, 2
|
17
|
+
end
|
18
|
+
|
19
|
+
if node.uses_apt? true
|
20
|
+
node.install_package 'git-core', false, 2
|
21
|
+
else
|
22
|
+
node.install_package 'git', false, 2
|
23
|
+
end
|
24
|
+
puts
|
25
|
+
|
26
|
+
# deploy basic configuration for root user
|
27
|
+
::Dust.print_msg "deploying configuration files for root\n", 1
|
28
|
+
Dir["#{template_path}/.*"].each do |file|
|
29
|
+
next unless File.file?(file)
|
30
|
+
node.scp file, "/root/#{File.basename(file)}", false, 2
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Debsecan < Thor
|
2
|
+
desc 'debsecan:deploy', 'installs and configures debian security package "debsecan"'
|
3
|
+
def deploy node, config, options
|
4
|
+
if node.is_os? ['debian', 'ubuntu'], true
|
5
|
+
node.install_package 'debsecan'
|
6
|
+
|
7
|
+
::Dust.print_msg 'configuring debsecan'
|
8
|
+
|
9
|
+
# if config is simply set to "true", use defaults
|
10
|
+
config = {} unless config.class == Hash
|
11
|
+
|
12
|
+
# setting default config variables (unless already set)
|
13
|
+
config['report'] ||= false
|
14
|
+
config['mailto'] ||= 'root'
|
15
|
+
config['source'] ||= ''
|
16
|
+
|
17
|
+
config_file = ''
|
18
|
+
|
19
|
+
# configures whether daily reports are sent
|
20
|
+
config_file += "# If true, enable daily reports, sent by email.\n" +
|
21
|
+
"REPORT=#{config['report'].to_s}\n\n"
|
22
|
+
|
23
|
+
# configures the suite
|
24
|
+
config_file += "# For better reporting, specify the correct suite here, using the code\n" +
|
25
|
+
"# name (that is, \"sid\" instead of \"unstable\").\n" +
|
26
|
+
"SUITE=#{node['lsbdistcodename']}\n\n"
|
27
|
+
|
28
|
+
# which user gets the reports?
|
29
|
+
config_file += "# Mail address to which reports are sent.\n" +
|
30
|
+
"MAILTO=#{config['mailto']}\n\n"
|
31
|
+
|
32
|
+
# set vulnerability source
|
33
|
+
config_file += "# The URL from which vulnerability data is downloaded. Empty for the\n" +
|
34
|
+
"# built-in default.\n" +
|
35
|
+
"SOURCE=#{config['source']}\n\n"
|
36
|
+
|
37
|
+
node.write '/etc/default/debsecan', config_file, true
|
38
|
+
::Dust.print_ok
|
39
|
+
else
|
40
|
+
::Dust.print_failed 'os not supported'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
class Duplicity < Thor
|
4
|
+
desc 'duplicity:deploy', 'installs and configures duplicity backups'
|
5
|
+
def deploy node, scenarios, options
|
6
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
7
|
+
|
8
|
+
return unless node.install_package 'duplicity'
|
9
|
+
|
10
|
+
# clear all other duplicity cronjobs that might have been deployed earlier
|
11
|
+
remove_duplicity_cronjobs node
|
12
|
+
|
13
|
+
# return if config simply says 'remove'
|
14
|
+
return if scenarios == 'remove'
|
15
|
+
|
16
|
+
scenarios.each do |scenario, conf|
|
17
|
+
config = conf.clone
|
18
|
+
|
19
|
+
# if directory config options is not given, use hostname-scenario
|
20
|
+
config['directory'] ||= "#{node['hostname']}-#{scenario}"
|
21
|
+
|
22
|
+
# check whether backend is specified, skip to next scenario if not
|
23
|
+
unless config['backend'] and config['passphrase']
|
24
|
+
::Dust.print_failed "scenario #{scenario}: backend or passphrase missing.", 1
|
25
|
+
next
|
26
|
+
end
|
27
|
+
|
28
|
+
# check if interval is correct
|
29
|
+
unless [ 'monthly', 'weekly', 'daily', 'hourly' ].include? config['interval']
|
30
|
+
return ::Dust.print_failed "invalid interval: '#{config['interval']}'"
|
31
|
+
end
|
32
|
+
|
33
|
+
# check whether we need ncftp
|
34
|
+
node.install_package 'ncftp' if config['backend'].include? 'ftp://'
|
35
|
+
|
36
|
+
# scp backend on centos needs python-pexpect
|
37
|
+
node.install_package 'python-pexpect' if config['backend'].include? 'scp://' and node.uses_rpm? true
|
38
|
+
|
39
|
+
# add hostkey to known_hosts
|
40
|
+
if config['hostkey']
|
41
|
+
::Dust.print_msg 'checking if ssh key is in known_hosts'
|
42
|
+
unless ::Dust.print_result node.exec("grep -q '#{config['hostkey']}' ~/.ssh/known_hosts")[:exit_code] == 0
|
43
|
+
node.mkdir '~/.ssh', false, 2
|
44
|
+
node.append '~/.ssh/known_hosts', config['hostkey'], false, 2
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# generate path for the cronjob
|
49
|
+
cronjob_path = "/etc/cron.#{config['interval']}/duplicity-#{scenario}"
|
50
|
+
|
51
|
+
# adjust and upload cronjob
|
52
|
+
template = ERB.new File.read("#{template_path}/cronjob.erb"), nil, '%<>'
|
53
|
+
::Dust.print_msg "adjusting and deploying cronjob (scenario: #{scenario}, interval: #{config['interval']})\n"
|
54
|
+
config['options'].each { |option| ::Dust.print_ok "adding option: #{option}", 2 }
|
55
|
+
node.write cronjob_path, template.result(binding)
|
56
|
+
|
57
|
+
# making cronjob executeable
|
58
|
+
node.chmod '0700', cronjob_path
|
59
|
+
puts
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# print duplicity-status
|
65
|
+
desc 'duplicity:status', 'displays current status of all duplicity backups'
|
66
|
+
def status node, scenarios, options
|
67
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
68
|
+
|
69
|
+
return unless node.package_installed? 'duplicity'
|
70
|
+
|
71
|
+
scenarios.each do |scenario, conf|
|
72
|
+
config = conf.clone
|
73
|
+
|
74
|
+
# if directory config option is not given, use hostname-scenario
|
75
|
+
config['directory'] ||= "#{node['hostname']}-#{scenario}"
|
76
|
+
|
77
|
+
# check whether backend is specified, skip to next scenario if not
|
78
|
+
return ::Dust.print_failed 'no backend specified.' unless config['backend']
|
79
|
+
|
80
|
+
::Dust.print_msg "running collection-status for scenario '#{scenario}'"
|
81
|
+
cmd = "nice -n #{config['nice']} duplicity collection-status " +
|
82
|
+
"--archive-dir #{config['archive']} " +
|
83
|
+
"#{File.join(config['backend'], config['directory'])}"
|
84
|
+
|
85
|
+
cmd += " |tail -n3 |head -n1" unless options.long?
|
86
|
+
|
87
|
+
ret = node.exec cmd
|
88
|
+
|
89
|
+
# check exit code and stdout shouldn't be empty
|
90
|
+
::Dust.print_result( (ret[:exit_code] == 0 and ret[:stdout].length > 0) )
|
91
|
+
|
92
|
+
if options.long?
|
93
|
+
::Dust.print_msg "#{::Dust.black}#{ret[:stdout]}#{::Dust.none}", 0
|
94
|
+
else
|
95
|
+
::Dust.print_msg "\t#{::Dust.black}#{ret[:stdout].sub(/^\s+([a-zA-Z]+)\s+(\w+\s+\w+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+(\d+)$/, 'Last backup: \1 (\3 sets) on \2')}#{::Dust.none}", 0
|
96
|
+
end
|
97
|
+
|
98
|
+
puts
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
# removes all duplicity cronjobs
|
104
|
+
def remove_duplicity_cronjobs node
|
105
|
+
::Dust.print_msg 'deleting old duplicity cronjobs'
|
106
|
+
node.rm '/etc/cron.*/duplicity*', true
|
107
|
+
::Dust.print_ok
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class EtcHosts < Thor
|
2
|
+
desc 'etc_hosts:deploy', 'deploys /etc/hosts'
|
3
|
+
def deploy node, daemon, options
|
4
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
5
|
+
|
6
|
+
return unless node.package_installed?('dnsmasq')
|
7
|
+
node.scp("#{template_path}/hosts", '/etc/hosts')
|
8
|
+
|
9
|
+
# restart dns service
|
10
|
+
node.restart_service daemon if options.restart?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,267 @@
|
|
1
|
+
class Iptables < Thor
|
2
|
+
desc 'iptables:deploy', 'configures iptables firewall'
|
3
|
+
def deploy node, rules, options
|
4
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
5
|
+
|
6
|
+
# install iptables
|
7
|
+
if node.uses_apt? true or node.uses_emerge? true
|
8
|
+
node.install_package 'iptables'
|
9
|
+
|
10
|
+
elsif node.uses_rpm? true
|
11
|
+
node.install_package 'iptables-ipv6'
|
12
|
+
|
13
|
+
else
|
14
|
+
::Dust.print_failed 'os not supported'
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
# configure attributes (using empty arrays as default)
|
19
|
+
rules['ports'] ||= []
|
20
|
+
rules['ipv4-custom-input-rules'] ||= []
|
21
|
+
rules['ipv6-custom-input-rules'] ||= []
|
22
|
+
rules['ipv4-custom-output-rules'] ||= []
|
23
|
+
rules['ipv6-custom-output-rules'] ||= []
|
24
|
+
rules['ipv4-custom-forward-rules'] ||= []
|
25
|
+
rules['ipv6-custom-forward-rules'] ||= []
|
26
|
+
rules['ipv4-custom-prerouting-rules'] ||= []
|
27
|
+
rules['ipv6-custom-prerouting-rules'] ||= []
|
28
|
+
rules['ipv4-custom-postrouting-rules'] ||= []
|
29
|
+
rules['ipv6-custom-postrouting-rules'] ||= []
|
30
|
+
|
31
|
+
# convert ports: int to array if its just a single int so .each won't get hickups
|
32
|
+
rules['ports'] = [ rules['ports'] ] if rules['ports'].class == Fixnum
|
33
|
+
|
34
|
+
[ 'iptables', 'ip6tables' ].each do |iptables|
|
35
|
+
ipv4 = iptables == 'iptables'
|
36
|
+
ipv6 = iptables == 'ip6tables'
|
37
|
+
|
38
|
+
::Dust.print_msg "configuring and deploying ipv4 rules\n" if ipv4
|
39
|
+
::Dust.print_msg "configuring and deploying ipv6 rules\n" if ipv6
|
40
|
+
|
41
|
+
rule_file = ''
|
42
|
+
|
43
|
+
# default policy for chains
|
44
|
+
if node.uses_apt? true or node.uses_emerge? true
|
45
|
+
rule_file += "-P INPUT DROP\n" +
|
46
|
+
"-P OUTPUT DROP\n" +
|
47
|
+
"-P FORWARD DROP\n" +
|
48
|
+
"-F\n"
|
49
|
+
rule_file += "-F -t nat\n" if ipv4
|
50
|
+
rule_file += "-X\n"
|
51
|
+
|
52
|
+
elsif node.uses_rpm? true
|
53
|
+
rule_file += "*filter\n" +
|
54
|
+
":INPUT DROP [0:0]\n" +
|
55
|
+
":FORWARD DROP [0:0]\n" +
|
56
|
+
":OUTPUT DROP [0:0]\n"
|
57
|
+
end
|
58
|
+
|
59
|
+
# allow localhost
|
60
|
+
rule_file += "-A INPUT -i lo -j ACCEPT\n"
|
61
|
+
|
62
|
+
# drop invalid packets
|
63
|
+
rule_file += "-A INPUT -m state --state INVALID -j DROP\n"
|
64
|
+
|
65
|
+
# allow related packets
|
66
|
+
rule_file += "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
|
67
|
+
|
68
|
+
# drop tcp packets with the syn bit set if the tcp connection is already established
|
69
|
+
rule_file += "-A INPUT -p tcp --tcp-flags SYN SYN -m state --state ESTABLISHED -j DROP\n" # if ipv4
|
70
|
+
|
71
|
+
# drop icmp timestamps
|
72
|
+
rule_file += "-A INPUT -p icmp --icmp-type timestamp-request -j DROP\n" if ipv4
|
73
|
+
rule_file += "-A INPUT -p icmp --icmp-type timestamp-reply -j DROP\n" if ipv4
|
74
|
+
|
75
|
+
# allow other icmp packets
|
76
|
+
rule_file += "-A INPUT -p icmpv6 -j ACCEPT\n" if ipv6
|
77
|
+
rule_file += "-A INPUT -p icmp -j ACCEPT\n"
|
78
|
+
|
79
|
+
# open ports
|
80
|
+
rules['ports'].each do |rule|
|
81
|
+
# if config is something like
|
82
|
+
# ports: 22
|
83
|
+
# or
|
84
|
+
# ports: [ 22, 443, 1000:2000 ]
|
85
|
+
# generate a new hash, and set rule['port']
|
86
|
+
unless rule.class == Hash
|
87
|
+
port = rule
|
88
|
+
rule = {}
|
89
|
+
rule['port'] = port
|
90
|
+
end
|
91
|
+
|
92
|
+
# skip rule for other ipversion than specified
|
93
|
+
rule['ip-version'] ||= 0 # default to 0, means both protocols
|
94
|
+
next if rule['ip-version'].to_i == 4 and ipv6
|
95
|
+
next if rule['ip-version'].to_i == 6 and ipv4
|
96
|
+
|
97
|
+
# convert to string if port is a int
|
98
|
+
rule['port'] = rule['port'].to_s if rule['port'].class == Fixnum
|
99
|
+
|
100
|
+
# skip this port if no portnumber is specified
|
101
|
+
unless rule['port']
|
102
|
+
::Dust.print_failed "no port specified: #{rule.inspect}", 2
|
103
|
+
next
|
104
|
+
end
|
105
|
+
|
106
|
+
# tcp is the default protocol
|
107
|
+
rule['protocol'] ||= 'tcp'
|
108
|
+
|
109
|
+
# apply one rule for each port(range)
|
110
|
+
rule['port'].each do |port|
|
111
|
+
::Dust.print_msg "allowing port #{port}:#{rule['protocol']}", 2
|
112
|
+
rule_file += "-A INPUT -p #{rule['protocol']} --dport #{port} "
|
113
|
+
if rule['interface']
|
114
|
+
print " [dev: #{rule['interface']}]"
|
115
|
+
rule_file += "-i #{rule['interface']} "
|
116
|
+
end
|
117
|
+
if rule['source']
|
118
|
+
print " [source: #{rule['source']}]"
|
119
|
+
rule_file += "--source #{rule['source']} "
|
120
|
+
end
|
121
|
+
rule_file += "-m state --state NEW "
|
122
|
+
rule_file += "-j ACCEPT\n"
|
123
|
+
::Dust.print_ok
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# add custom ipv4 iput rules
|
128
|
+
rules['ipv4-custom-input-rules'].each do |rule|
|
129
|
+
::Dust.print_msg "adding custom ipv4 input rule: #{rule}", 2
|
130
|
+
rule_file += "-A INPUT #{rule}\n"
|
131
|
+
::Dust.print_ok
|
132
|
+
end if ipv4
|
133
|
+
|
134
|
+
# add custom ipv6 iput rules
|
135
|
+
rules['ipv6-custom-input-rules'].each do |rule|
|
136
|
+
::Dust.print_msg "adding custom ipv6 input rule: #{rule}", 2
|
137
|
+
rule_file += "-A INPUT #{rule}\n"
|
138
|
+
::Dust.print_ok
|
139
|
+
end if ipv6
|
140
|
+
|
141
|
+
# deny the rest
|
142
|
+
rule_file += "-A INPUT -p tcp -j REJECT --reject-with tcp-reset\n"
|
143
|
+
rule_file += "-A INPUT -j REJECT --reject-with icmp-port-unreachable\n" if ipv4
|
144
|
+
|
145
|
+
# add custom ipv4 prerouting rules
|
146
|
+
rules['ipv4-custom-prerouting-rules'].each do |rule|
|
147
|
+
::Dust.print_msg "adding custom ipv4 prerouting rule: #{rule}", 2
|
148
|
+
rule_file += "-A PREROUTING #{rule}\n"
|
149
|
+
::Dust.print_ok
|
150
|
+
end if ipv4
|
151
|
+
|
152
|
+
# add custom ipv6 prerouting rules
|
153
|
+
rules['ipv6-custom-prerouting-rules'].each do |rule|
|
154
|
+
::Dust.print_msg "adding custom ipv6 prerouting rule: #{rule}", 2
|
155
|
+
rule_file += "-A PREROUTING #{rule}\n"
|
156
|
+
::Dust.print_ok
|
157
|
+
end if ipv6
|
158
|
+
|
159
|
+
# add custom ipv4 postrouting rules
|
160
|
+
rules['ipv4-custom-postrouting-rules'].each do |rule|
|
161
|
+
::Dust.print_msg "adding custom ipv4 postrouting rule: #{rule}", 2
|
162
|
+
rule_file += "-A POSTROUTING #{rule}\n"
|
163
|
+
::Dust.print_ok
|
164
|
+
end if ipv4
|
165
|
+
|
166
|
+
# add custom ipv6 postrouting rules
|
167
|
+
rules['ipv6-custom-postrouting-rules'].each do |rule|
|
168
|
+
::Dust.print_msg "adding custom ipv6 postrouting rule: #{rule}", 2
|
169
|
+
rule_file += "-A POSTROUTING #{rule}\n"
|
170
|
+
::Dust.print_ok
|
171
|
+
end if ipv6
|
172
|
+
|
173
|
+
|
174
|
+
# drop invalid outgoing packets
|
175
|
+
rule_file += "-A OUTPUT -m state --state INVALID -j DROP\n"
|
176
|
+
|
177
|
+
# allow related outgoing packets
|
178
|
+
rule_file += "-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
|
179
|
+
|
180
|
+
# add custom ipv4 output rules
|
181
|
+
rules['ipv4-custom-output-rules'].each do |rule|
|
182
|
+
::Dust.print_msg "adding custom ipv4 outgoing rule: #{rule}", 2
|
183
|
+
rule_file += "-A OUTPUT #{rule}\n"
|
184
|
+
::Dust.print_ok
|
185
|
+
end if ipv4
|
186
|
+
|
187
|
+
# add custom ipv6 output rules
|
188
|
+
rules['ipv6-custom-output-rules'].each do |rule|
|
189
|
+
::Dust.print_msg "adding custom ipv6 outgoing rule: #{rule}", 2
|
190
|
+
rule_file += "-A OUTPUT #{rule}\n"
|
191
|
+
::Dust.print_ok
|
192
|
+
end if ipv6
|
193
|
+
|
194
|
+
# allow everything out
|
195
|
+
rule_file += "-A OUTPUT -j ACCEPT\n"
|
196
|
+
|
197
|
+
|
198
|
+
# enable packet forwarding
|
199
|
+
if rules['forward']
|
200
|
+
::Dust.print_msg 'enabling ipv4 forwarding', 2
|
201
|
+
rule_file += "-A FORWARD -m state --state INVALID -j DROP\n"
|
202
|
+
rule_file += "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
|
203
|
+
rule_file += "-A FORWARD -j ACCEPT\n"
|
204
|
+
::Dust.print_ok
|
205
|
+
end if ipv4
|
206
|
+
|
207
|
+
# add custom ipv4 forward rules
|
208
|
+
rules['ipv4-custom-forward-rules'].each do |rule|
|
209
|
+
::Dust.print_msg "adding custom ipv4 forward rule: #{rule}", 2
|
210
|
+
rule_file += "-A FORWARD #{rule}\n"
|
211
|
+
::Dust.print_ok
|
212
|
+
end if ipv4
|
213
|
+
|
214
|
+
# add custom ipv6 forward rules
|
215
|
+
rules['ipv6-custom-forward-rules'].each do |rule|
|
216
|
+
::Dust.print_msg "adding custom ipv6 forward rule: #{rule}", 2
|
217
|
+
rule_file += "-A FORWARD #{rule}\n"
|
218
|
+
::Dust.print_ok
|
219
|
+
end if ipv6
|
220
|
+
|
221
|
+
rule_file += "COMMIT\n" if node.uses_rpm? true
|
222
|
+
|
223
|
+
# prepend iptables command on non-centos-like machines
|
224
|
+
rule_file = rule_file.map { |s| "#{iptables} #{s}" }.to_s if node.uses_apt? true or node.uses_emerge? true
|
225
|
+
|
226
|
+
# set header
|
227
|
+
header = ''
|
228
|
+
header = "#!/bin/sh\n" if node.uses_apt? true or node.uses_emerge? true
|
229
|
+
header += "# automatically generated by dust\n\n"
|
230
|
+
rule_file = header + rule_file
|
231
|
+
|
232
|
+
# set the target file depending on distribution
|
233
|
+
target = "/etc/network/if-pre-up.d/#{iptables}" if node.uses_apt? true
|
234
|
+
target = "/etc/#{iptables}" if node.uses_emerge? true
|
235
|
+
target = "/etc/sysconfig/#{iptables}" if node.uses_rpm? true
|
236
|
+
|
237
|
+
node.write target, rule_file, true
|
238
|
+
|
239
|
+
node.chmod '700', target if node.uses_apt? true or node.uses_emerge? true
|
240
|
+
node.chmod '600', target if node.uses_rpm? true
|
241
|
+
|
242
|
+
if options.restart?
|
243
|
+
::Dust.print_msg 'applying ipv4 rules' if ipv4
|
244
|
+
::Dust.print_msg 'applying ipv6 rules' if ipv6
|
245
|
+
|
246
|
+
if node.uses_rpm? true
|
247
|
+
::Dust.print_result node.exec("/etc/init.d/#{iptables} restart")[:exit_code]
|
248
|
+
|
249
|
+
elsif node.uses_apt? true or node.uses_emerge? true
|
250
|
+
ret = node.exec target
|
251
|
+
::Dust.print_result( (ret[:exit_code] == 0 and ret[:stdout].empty? and ret[:stderr].empty?) )
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# on gentoo, rules have to be saved using the init script,
|
256
|
+
# otherwise they won't get re-applied on next startup
|
257
|
+
if node.uses_emerge? true
|
258
|
+
::Dust.print_msg 'saving ipv4 rules' if ipv4
|
259
|
+
::Dust.print_msg 'saving ipv6 rules' if ipv6
|
260
|
+
::Dust.print_result node.exec("/etc/init.d/#{iptables} save")[:exit_code]
|
261
|
+
end
|
262
|
+
|
263
|
+
puts
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|