Force bond interfaces to be a plain array
[chef.git] / cookbooks / networking / recipes / default.rb
1 #
2 # Cookbook Name:: networking
3 # Recipe:: default
4 #
5 # Copyright 2010, OpenStreetMap Foundation.
6 # Copyright 2009, Opscode, Inc.
7 #
8 # Licensed under the Apache License, Version 2.0 (the "License");
9 # you may not use this file except in compliance with the License.
10 # You may obtain a copy of the License at
11 #
12 #     https://www.apache.org/licenses/LICENSE-2.0
13 #
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
19 #
20 # = Requires
21 # * node[:networking][:nameservers]
22
23 require "ipaddr"
24 require "yaml"
25
26 network_packages = []
27
28 netplan = {
29   "network" => {
30     "version" => 2,
31     "renderer" => "networkd",
32     "ethernets" => {},
33     "bonds" => {},
34     "vlans" => {}
35   }
36 }
37
38 node[:networking][:interfaces].each do |name, interface|
39   if interface[:interface]
40     network_packages |= ["vlan"] if interface[:interface] =~ /\.\d+$/
41     network_packages |= ["ifenslave"] if interface[:bond]
42
43     if interface[:role] && (role = node[:networking][:roles][interface[:role]])
44       if role[interface[:family]]
45         node.normal[:networking][:interfaces][name][:prefix] = role[interface[:family]][:prefix]
46         node.normal[:networking][:interfaces][name][:gateway] = role[interface[:family]][:gateway]
47       end
48
49       node.normal[:networking][:interfaces][name][:metric] = role[:metric]
50       node.normal[:networking][:interfaces][name][:zone] = role[:zone]
51     end
52
53     prefix = node[:networking][:interfaces][name][:prefix]
54
55     node.normal[:networking][:interfaces][name][:netmask] = (~IPAddr.new(interface[:address]).mask(0)).mask(prefix)
56     node.normal[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
57
58     if node[:networking][:netplan]
59       if interface[:interface] =~ /^(.*)\.(\d+)$/
60         deviceplan = netplan["network"]["vlans"][interface[:interface]] = {
61           "id" => Regexp.last_match(2).to_i,
62           "link" => Regexp.last_match(1),
63           "accept-ra" => false,
64           "addresses" => [],
65           "routes" => []
66         }
67       elsif interface[:bond]
68         deviceplan = netplan["network"]["bonds"][interface[:interface]] = {
69           "accept-ra" => false,
70           "addresses" => [],
71           "routes" => [],
72           "interfaces" => interface[:bond][:slaves].to_a,
73           "mode" => interface[:bond][:mode] || "active-backup",
74           "primary" => interface[:bond][:slaves].first,
75           "mii-monitor-interval" => interface[:bond][:miimon] || 100,
76           "down-delay" => interface[:bond][:downdelay] || 200,
77           "up-delay" => interface[:bond][:updelay] || 200
78         }
79
80         deviceplan["transmit-hash-policy"] = interface[:bond][:xmithashpolicy] if interface[:bond][:xmithashpolicy]
81         deviceplan["lacp-rate"] = interface[:bond][:lacprate] if interface[:bond][:lacprate]
82       else
83         deviceplan = netplan["network"]["ethernets"][interface[:interface]] = {
84           "accept-ra" => false,
85           "addresses" => [],
86           "routes" => []
87         }
88       end
89
90       deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
91
92       if interface[:gateway]
93         if interface[:family] == "inet"
94           default_route = "0.0.0.0/0"
95         elsif interface[:family] == "inet6"
96           default_route = "::/0"
97         end
98
99         deviceplan["routes"].push(
100           "to" => default_route,
101           "via" => interface[:gateway],
102           "metric" => interface[:metric],
103           "on-link" => true
104         )
105       end
106     end
107   else
108     node.rm(:networking, :interfaces, name)
109   end
110 end
111
112 if node[:networking][:netplan]
113   package "netplan.io"
114
115   file "/etc/netplan/01-netcfg.yaml" do
116     action :delete
117   end
118
119   netplan["network"]["bonds"].each_value do |bond|
120     bond["interfaces"].each do |interface|
121       netplan["network"]["ethernets"][interface] ||= { "accept-ra" => false }
122     end
123   end
124
125   netplan["network"]["vlans"].each_value do |vlan|
126     netplan["network"]["ethernets"][vlan["link"]] ||= { "accept-ra" => false }
127   end
128
129   file "/etc/netplan/99-chef.yaml" do
130     owner "root"
131     group "root"
132     mode 0o644
133     content YAML.dump(netplan)
134   end
135
136   service "networking" do
137     action :disable
138   end
139
140   file "/etc/network/interfaces" do
141     action :delete
142   end
143
144   package "ifupdown" do
145     action :purge
146   end
147 else
148   package network_packages
149
150   template "/etc/network/interfaces" do
151     source "interfaces.erb"
152     owner "root"
153     group "root"
154     mode 0o644
155   end
156 end
157
158 execute "hostname" do
159   action :nothing
160   command "/bin/hostname -F /etc/hostname"
161 end
162
163 template "/etc/hostname" do
164   source "hostname.erb"
165   owner "root"
166   group "root"
167   mode 0o644
168   notifies :run, "execute[hostname]"
169 end
170
171 template "/etc/hosts" do
172   source "hosts.erb"
173   owner "root"
174   group "root"
175   mode 0o644
176 end
177
178 unless node[:networking][:nameservers].empty?
179   link "/etc/resolv.conf" do
180     action :delete
181     link_type :symbolic
182     to "/run/resolvconf/resolv.conf"
183     only_if { File.symlink?("/etc/resolv.conf") }
184   end
185
186   template "/etc/resolv.conf" do
187     source "resolv.conf.erb"
188     owner "root"
189     group "root"
190     mode 0o644
191   end
192 end
193
194 node.interfaces(:role => :internal) do |interface|
195   if interface[:gateway] && interface[:gateway] != interface[:address]
196     search(:node, "networking_interfaces*address:#{interface[:gateway]}") do |gateway|
197       next unless gateway[:openvpn]
198
199       gateway[:openvpn][:tunnels].each_value do |tunnel|
200         if tunnel[:peer][:address] # ~FC023
201           route tunnel[:peer][:address] do
202             netmask "255.255.255.255"
203             gateway interface[:gateway]
204             device interface[:interface]
205           end
206         end
207
208         next unless tunnel[:peer][:networks]
209
210         tunnel[:peer][:networks].each do |network|
211           route network[:address] do
212             netmask network[:netmask]
213             gateway interface[:gateway]
214             device interface[:interface]
215           end
216         end
217       end
218     end
219   end
220 end
221
222 zones = {}
223
224 search(:node, "networking:interfaces").collect do |n|
225   next if n[:fqdn] == node[:fqdn]
226
227   n.interfaces.each do |interface|
228     next unless interface[:role] == "external" && interface[:zone]
229
230     zones[interface[:zone]] ||= {}
231     zones[interface[:zone]][interface[:family]] ||= []
232     zones[interface[:zone]][interface[:family]] << interface[:address]
233   end
234 end
235
236 package "shorewall"
237
238 template "/etc/default/shorewall" do
239   source "shorewall-default.erb"
240   owner "root"
241   group "root"
242   mode 0o644
243   notifies :restart, "service[shorewall]"
244 end
245
246 template "/etc/shorewall/shorewall.conf" do
247   source "shorewall.conf.erb"
248   owner "root"
249   group "root"
250   mode 0o644
251   notifies :restart, "service[shorewall]"
252 end
253
254 template "/etc/shorewall/zones" do
255   source "shorewall-zones.erb"
256   owner "root"
257   group "root"
258   mode 0o644
259   variables :type => "ipv4"
260   notifies :restart, "service[shorewall]"
261 end
262
263 template "/etc/shorewall/interfaces" do
264   source "shorewall-interfaces.erb"
265   owner "root"
266   group "root"
267   mode 0o644
268   notifies :restart, "service[shorewall]"
269 end
270
271 template "/etc/shorewall/hosts" do
272   source "shorewall-hosts.erb"
273   owner "root"
274   group "root"
275   mode 0o644
276   variables :zones => zones
277   notifies :restart, "service[shorewall]"
278 end
279
280 template "/etc/shorewall/conntrack" do
281   source "shorewall-conntrack.erb"
282   owner "root"
283   group "root"
284   mode 0o644
285   notifies :restart, "service[shorewall]"
286   only_if { node[:networking][:firewall][:raw] }
287 end
288
289 template "/etc/shorewall/policy" do
290   source "shorewall-policy.erb"
291   owner "root"
292   group "root"
293   mode 0o644
294   notifies :restart, "service[shorewall]"
295 end
296
297 template "/etc/shorewall/rules" do
298   source "shorewall-rules.erb"
299   owner "root"
300   group "root"
301   mode 0o644
302   variables :family => "inet"
303   notifies :restart, "service[shorewall]"
304 end
305
306 service "shorewall" do
307   action [:enable, :start]
308   supports :restart => true
309   status_command "shorewall status"
310 end
311
312 template "/etc/logrotate.d/shorewall" do
313   source "logrotate.shorewall.erb"
314   owner "root"
315   group "root"
316   mode 0o644
317   variables :name => "shorewall"
318 end
319
320 firewall_rule "limit-icmp-echo" do
321   action :accept
322   family :inet
323   source "net"
324   dest "fw"
325   proto "icmp"
326   dest_ports "echo-request"
327   rate_limit "s:1/sec:5"
328 end
329
330 %w[ucl ams bm].each do |zone|
331   firewall_rule "accept-openvpn-#{zone}" do
332     action :accept
333     source zone
334     dest "fw"
335     proto "udp"
336     dest_ports "1194:1197"
337     source_ports "1194:1197"
338   end
339 end
340
341 if node[:roles].include?("gateway")
342   template "/etc/shorewall/masq" do
343     source "shorewall-masq.erb"
344     owner "root"
345     group "root"
346     mode 0o644
347     notifies :restart, "service[shorewall]"
348   end
349 else
350   file "/etc/shorewall/masq" do
351     action :delete
352     notifies :restart, "service[shorewall]"
353   end
354 end
355
356 unless node.interfaces(:family => :inet6).empty?
357   package "shorewall6"
358
359   template "/etc/default/shorewall6" do
360     source "shorewall-default.erb"
361     owner "root"
362     group "root"
363     mode 0o644
364     notifies :restart, "service[shorewall6]"
365   end
366
367   template "/etc/shorewall6/shorewall6.conf" do
368     source "shorewall6.conf.erb"
369     owner "root"
370     group "root"
371     mode 0o644
372     notifies :restart, "service[shorewall6]"
373   end
374
375   template "/etc/shorewall6/zones" do
376     source "shorewall-zones.erb"
377     owner "root"
378     group "root"
379     mode 0o644
380     variables :type => "ipv6"
381     notifies :restart, "service[shorewall6]"
382   end
383
384   template "/etc/shorewall6/interfaces" do
385     source "shorewall6-interfaces.erb"
386     owner "root"
387     group "root"
388     mode 0o644
389     notifies :restart, "service[shorewall6]"
390   end
391
392   template "/etc/shorewall6/hosts" do
393     source "shorewall6-hosts.erb"
394     owner "root"
395     group "root"
396     mode 0o644
397     variables :zones => zones
398     notifies :restart, "service[shorewall6]"
399   end
400
401   template "/etc/shorewall6/conntrack" do
402     source "shorewall-conntrack.erb"
403     owner "root"
404     group "root"
405     mode 0o644
406     notifies :restart, "service[shorewall6]"
407     only_if { node[:networking][:firewall][:raw] }
408   end
409
410   template "/etc/shorewall6/policy" do
411     source "shorewall-policy.erb"
412     owner "root"
413     group "root"
414     mode 0o644
415     notifies :restart, "service[shorewall6]"
416   end
417
418   template "/etc/shorewall6/rules" do
419     source "shorewall-rules.erb"
420     owner "root"
421     group "root"
422     mode 0o644
423     variables :family => "inet6"
424     notifies :restart, "service[shorewall6]"
425   end
426
427   service "shorewall6" do
428     action [:enable, :start]
429     supports :restart => true
430     status_command "shorewall6 status"
431   end
432
433   template "/etc/logrotate.d/shorewall6" do
434     source "logrotate.shorewall.erb"
435     owner "root"
436     group "root"
437     mode 0o644
438     variables :name => "shorewall6"
439   end
440
441   firewall_rule "limit-icmp6-echo" do
442     action :accept
443     family :inet6
444     source "net"
445     dest "fw"
446     proto "ipv6-icmp"
447     dest_ports "echo-request"
448     rate_limit "s:1/sec:5"
449   end
450 end
451
452 firewall_rule "accept-http" do
453   action :accept
454   source "net"
455   dest "fw"
456   proto "tcp:syn"
457   dest_ports "http"
458   rate_limit node[:networking][:firewall][:http_rate_limit]
459   connection_limit node[:networking][:firewall][:http_connection_limit]
460 end
461
462 firewall_rule "accept-https" do
463   action :accept
464   source "net"
465   dest "fw"
466   proto "tcp:syn"
467   dest_ports "https"
468   rate_limit node[:networking][:firewall][:http_rate_limit]
469   connection_limit node[:networking][:firewall][:http_connection_limit]
470 end