]> git.openstreetmap.org Git - chef.git/blob - cookbooks/networking/recipes/default.rb
Handle interfaces with multiple addresses
[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       deviceplan = if interface[:interface] =~ /^(.*)\.(\d+)$/
60                      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[:interface] =~ /^bond\d+$/
68                      netplan["network"]["bonds"][interface[:interface]] ||= {
69                        "accept-ra" => false,
70                        "addresses" => [],
71                        "routes" => []
72                      }
73                    else
74                      netplan["network"]["ethernets"][interface[:interface]] ||= {
75                        "accept-ra" => false,
76                        "addresses" => [],
77                        "routes" => []
78                      }
79                    end
80
81       deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
82
83       if interface[:bond]
84         deviceplan["interfaces"] = interface[:bond][:slaves].to_a
85
86         deviceplan["parameters"] = {
87           "mode" => interface[:bond][:mode] || "active-backup",
88           "primary" => interface[:bond][:slaves].first,
89           "mii-monitor-interval" => interface[:bond][:miimon] || 100,
90           "down-delay" => interface[:bond][:downdelay] || 200,
91           "up-delay" => interface[:bond][:updelay] || 200
92         }
93
94         deviceplan["parameters"]["transmit-hash-policy"] = interface[:bond][:xmithashpolicy] if interface[:bond][:xmithashpolicy]
95         deviceplan["parameters"]["lacp-rate"] = interface[:bond][:lacprate] if interface[:bond][:lacprate]
96       end
97
98       if interface[:gateway]
99         if interface[:family] == "inet"
100           default_route = "0.0.0.0/0"
101         elsif interface[:family] == "inet6"
102           default_route = "::/0"
103         end
104
105         deviceplan["routes"].push(
106           "to" => default_route,
107           "via" => interface[:gateway],
108           "metric" => interface[:metric],
109           "on-link" => true
110         )
111       end
112     end
113   else
114     node.rm(:networking, :interfaces, name)
115   end
116 end
117
118 if node[:networking][:netplan]
119   package "netplan.io"
120
121   file "/etc/netplan/01-netcfg.yaml" do
122     action :delete
123   end
124
125   netplan["network"]["bonds"].each_value do |bond|
126     bond["interfaces"].each do |interface|
127       netplan["network"]["ethernets"][interface] ||= { "accept-ra" => false }
128     end
129   end
130
131   netplan["network"]["vlans"].each_value do |vlan|
132     unless vlan["link"] =~ /^bond\d+$/
133       netplan["network"]["ethernets"][vlan["link"]] ||= { "accept-ra" => false }
134     end
135   end
136
137   file "/etc/netplan/99-chef.yaml" do
138     owner "root"
139     group "root"
140     mode 0o644
141     content YAML.dump(netplan)
142   end
143
144   service "networking" do
145     action :disable
146   end
147
148   file "/etc/network/interfaces" do
149     action :delete
150   end
151
152   package "ifupdown" do
153     action :purge
154   end
155 else
156   package network_packages
157
158   template "/etc/network/interfaces" do
159     source "interfaces.erb"
160     owner "root"
161     group "root"
162     mode 0o644
163   end
164 end
165
166 execute "hostname" do
167   action :nothing
168   command "/bin/hostname -F /etc/hostname"
169 end
170
171 template "/etc/hostname" do
172   source "hostname.erb"
173   owner "root"
174   group "root"
175   mode 0o644
176   notifies :run, "execute[hostname]"
177 end
178
179 template "/etc/hosts" do
180   source "hosts.erb"
181   owner "root"
182   group "root"
183   mode 0o644
184 end
185
186 unless node[:networking][:nameservers].empty?
187   link "/etc/resolv.conf" do
188     action :delete
189     link_type :symbolic
190     to "/run/resolvconf/resolv.conf"
191     only_if { File.symlink?("/etc/resolv.conf") }
192   end
193
194   template "/etc/resolv.conf" do
195     source "resolv.conf.erb"
196     owner "root"
197     group "root"
198     mode 0o644
199   end
200 end
201
202 node.interfaces(:role => :internal) do |interface|
203   if interface[:gateway] && interface[:gateway] != interface[:address]
204     search(:node, "networking_interfaces*address:#{interface[:gateway]}") do |gateway|
205       next unless gateway[:openvpn]
206
207       gateway[:openvpn][:tunnels].each_value do |tunnel|
208         if tunnel[:peer][:address] # ~FC023
209           route tunnel[:peer][:address] do
210             netmask "255.255.255.255"
211             gateway interface[:gateway]
212             device interface[:interface]
213           end
214         end
215
216         next unless tunnel[:peer][:networks]
217
218         tunnel[:peer][:networks].each do |network|
219           route network[:address] do
220             netmask network[:netmask]
221             gateway interface[:gateway]
222             device interface[:interface]
223           end
224         end
225       end
226     end
227   end
228 end
229
230 zones = {}
231
232 search(:node, "networking:interfaces").collect do |n|
233   next if n[:fqdn] == node[:fqdn]
234
235   n.interfaces.each do |interface|
236     next unless interface[:role] == "external" && interface[:zone]
237
238     zones[interface[:zone]] ||= {}
239     zones[interface[:zone]][interface[:family]] ||= []
240     zones[interface[:zone]][interface[:family]] << interface[:address]
241   end
242 end
243
244 package "shorewall"
245
246 template "/etc/default/shorewall" do
247   source "shorewall-default.erb"
248   owner "root"
249   group "root"
250   mode 0o644
251   notifies :restart, "service[shorewall]"
252 end
253
254 template "/etc/shorewall/shorewall.conf" do
255   source "shorewall.conf.erb"
256   owner "root"
257   group "root"
258   mode 0o644
259   notifies :restart, "service[shorewall]"
260 end
261
262 template "/etc/shorewall/zones" do
263   source "shorewall-zones.erb"
264   owner "root"
265   group "root"
266   mode 0o644
267   variables :type => "ipv4"
268   notifies :restart, "service[shorewall]"
269 end
270
271 template "/etc/shorewall/interfaces" do
272   source "shorewall-interfaces.erb"
273   owner "root"
274   group "root"
275   mode 0o644
276   notifies :restart, "service[shorewall]"
277 end
278
279 template "/etc/shorewall/hosts" do
280   source "shorewall-hosts.erb"
281   owner "root"
282   group "root"
283   mode 0o644
284   variables :zones => zones
285   notifies :restart, "service[shorewall]"
286 end
287
288 template "/etc/shorewall/conntrack" do
289   source "shorewall-conntrack.erb"
290   owner "root"
291   group "root"
292   mode 0o644
293   notifies :restart, "service[shorewall]"
294   only_if { node[:networking][:firewall][:raw] }
295 end
296
297 template "/etc/shorewall/policy" do
298   source "shorewall-policy.erb"
299   owner "root"
300   group "root"
301   mode 0o644
302   notifies :restart, "service[shorewall]"
303 end
304
305 template "/etc/shorewall/rules" do
306   source "shorewall-rules.erb"
307   owner "root"
308   group "root"
309   mode 0o644
310   variables :family => "inet"
311   notifies :restart, "service[shorewall]"
312 end
313
314 service "shorewall" do
315   action [:enable, :start]
316   supports :restart => true
317   status_command "shorewall status"
318 end
319
320 template "/etc/logrotate.d/shorewall" do
321   source "logrotate.shorewall.erb"
322   owner "root"
323   group "root"
324   mode 0o644
325   variables :name => "shorewall"
326 end
327
328 firewall_rule "limit-icmp-echo" do
329   action :accept
330   family :inet
331   source "net"
332   dest "fw"
333   proto "icmp"
334   dest_ports "echo-request"
335   rate_limit "s:1/sec:5"
336 end
337
338 %w[ucl ams bm].each do |zone|
339   firewall_rule "accept-openvpn-#{zone}" do
340     action :accept
341     source zone
342     dest "fw"
343     proto "udp"
344     dest_ports "1194:1197"
345     source_ports "1194:1197"
346   end
347 end
348
349 if node[:roles].include?("gateway")
350   template "/etc/shorewall/masq" do
351     source "shorewall-masq.erb"
352     owner "root"
353     group "root"
354     mode 0o644
355     notifies :restart, "service[shorewall]"
356   end
357 else
358   file "/etc/shorewall/masq" do
359     action :delete
360     notifies :restart, "service[shorewall]"
361   end
362 end
363
364 unless node.interfaces(:family => :inet6).empty?
365   package "shorewall6"
366
367   template "/etc/default/shorewall6" do
368     source "shorewall-default.erb"
369     owner "root"
370     group "root"
371     mode 0o644
372     notifies :restart, "service[shorewall6]"
373   end
374
375   template "/etc/shorewall6/shorewall6.conf" do
376     source "shorewall6.conf.erb"
377     owner "root"
378     group "root"
379     mode 0o644
380     notifies :restart, "service[shorewall6]"
381   end
382
383   template "/etc/shorewall6/zones" do
384     source "shorewall-zones.erb"
385     owner "root"
386     group "root"
387     mode 0o644
388     variables :type => "ipv6"
389     notifies :restart, "service[shorewall6]"
390   end
391
392   template "/etc/shorewall6/interfaces" do
393     source "shorewall6-interfaces.erb"
394     owner "root"
395     group "root"
396     mode 0o644
397     notifies :restart, "service[shorewall6]"
398   end
399
400   template "/etc/shorewall6/hosts" do
401     source "shorewall6-hosts.erb"
402     owner "root"
403     group "root"
404     mode 0o644
405     variables :zones => zones
406     notifies :restart, "service[shorewall6]"
407   end
408
409   template "/etc/shorewall6/conntrack" do
410     source "shorewall-conntrack.erb"
411     owner "root"
412     group "root"
413     mode 0o644
414     notifies :restart, "service[shorewall6]"
415     only_if { node[:networking][:firewall][:raw] }
416   end
417
418   template "/etc/shorewall6/policy" do
419     source "shorewall-policy.erb"
420     owner "root"
421     group "root"
422     mode 0o644
423     notifies :restart, "service[shorewall6]"
424   end
425
426   template "/etc/shorewall6/rules" do
427     source "shorewall-rules.erb"
428     owner "root"
429     group "root"
430     mode 0o644
431     variables :family => "inet6"
432     notifies :restart, "service[shorewall6]"
433   end
434
435   service "shorewall6" do
436     action [:enable, :start]
437     supports :restart => true
438     status_command "shorewall6 status"
439   end
440
441   template "/etc/logrotate.d/shorewall6" do
442     source "logrotate.shorewall.erb"
443     owner "root"
444     group "root"
445     mode 0o644
446     variables :name => "shorewall6"
447   end
448
449   firewall_rule "limit-icmp6-echo" do
450     action :accept
451     family :inet6
452     source "net"
453     dest "fw"
454     proto "ipv6-icmp"
455     dest_ports "echo-request"
456     rate_limit "s:1/sec:5"
457   end
458 end
459
460 firewall_rule "accept-http" do
461   action :accept
462   source "net"
463   dest "fw"
464   proto "tcp:syn"
465   dest_ports "http"
466   rate_limit node[:networking][:firewall][:http_rate_limit]
467   connection_limit node[:networking][:firewall][:http_connection_limit]
468 end
469
470 firewall_rule "accept-https" do
471   action :accept
472   source "net"
473   dest "fw"
474   proto "tcp:syn"
475   dest_ports "https"
476   rate_limit node[:networking][:firewall][:http_rate_limit]
477   connection_limit node[:networking][:firewall][:http_connection_limit]
478 end