8b6b1f35f64f6a3f7c53585d960c870035e93b25
[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 netplan = {
27   "network" => {
28     "version" => 2,
29     "renderer" => "networkd",
30     "ethernets" => {},
31     "bonds" => {},
32     "vlans" => {}
33   }
34 }
35
36 node[:networking][:interfaces].each do |name, interface|
37   if interface[:interface]
38     if interface[:role] && (role = node[:networking][:roles][interface[:role]])
39       if role[interface[:family]]
40         node.normal[:networking][:interfaces][name][:prefix] = role[interface[:family]][:prefix]
41         node.normal[:networking][:interfaces][name][:gateway] = role[interface[:family]][:gateway]
42       end
43
44       node.normal[:networking][:interfaces][name][:metric] = role[:metric]
45       node.normal[:networking][:interfaces][name][:zone] = role[:zone]
46     end
47
48     prefix = node[:networking][:interfaces][name][:prefix]
49
50     node.normal[:networking][:interfaces][name][:netmask] = (~IPAddr.new(interface[:address]).mask(0)).mask(prefix)
51     node.normal[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
52
53     interface = node[:networking][:interfaces][name]
54
55     deviceplan = if interface[:interface] =~ /^(.*)\.(\d+)$/
56                    netplan["network"]["vlans"][interface[:interface]] ||= {
57                      "id" => Regexp.last_match(2).to_i,
58                      "link" => Regexp.last_match(1),
59                      "accept-ra" => false,
60                      "addresses" => [],
61                      "routes" => []
62                    }
63                  elsif interface[:interface] =~ /^bond\d+$/
64                    netplan["network"]["bonds"][interface[:interface]] ||= {
65                      "accept-ra" => false,
66                      "addresses" => [],
67                      "routes" => []
68                    }
69                  else
70                    netplan["network"]["ethernets"][interface[:interface]] ||= {
71                      "accept-ra" => false,
72                      "addresses" => [],
73                      "routes" => []
74                    }
75                  end
76
77     deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
78
79     if interface[:mtu]
80       deviceplan["mtu"] = interface[:mtu]
81     end
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
112       # This ordering relies on systemd-networkd adding routes
113       # in reverse order and will need moving before the previous
114       # route once that is fixed:
115       #
116       # https://github.com/systemd/systemd/issues/5430
117       # https://github.com/systemd/systemd/pull/10938
118       if interface[:family] == "inet6" &&
119          !interface[:network].include?(interface[:gateway]) &&
120          !IPAddr.new("fe80::/64").include?(interface[:gateway])
121         deviceplan["routes"].push(
122           "to" => interface[:gateway],
123           "scope" => "link"
124         )
125       end
126     end
127   else
128     node.rm(:networking, :interfaces, name)
129   end
130 end
131
132 netplan["network"]["bonds"].each_value do |bond|
133   bond["interfaces"].each do |interface|
134     netplan["network"]["ethernets"][interface] ||= { "accept-ra" => false }
135   end
136 end
137
138 netplan["network"]["vlans"].each_value do |vlan|
139   unless vlan["link"] =~ /^bond\d+$/
140     netplan["network"]["ethernets"][vlan["link"]] ||= { "accept-ra" => false }
141   end
142 end
143
144 file "/etc/netplan/01-netcfg.yaml" do
145   action :delete
146 end
147
148 file "/etc/netplan/50-cloud-init.yaml" do
149   action :delete
150 end
151
152 file "/etc/netplan/99-chef.yaml" do
153   owner "root"
154   group "root"
155   mode 0o644
156   content YAML.dump(netplan)
157 end
158
159 package "cloud-init" do
160   action :purge
161 end
162
163 execute "hostname" do
164   action :nothing
165   command "/bin/hostname -F /etc/hostname"
166 end
167
168 template "/etc/hostname" do
169   source "hostname.erb"
170   owner "root"
171   group "root"
172   mode 0o644
173   notifies :run, "execute[hostname]"
174 end
175
176 template "/etc/hosts" do
177   source "hosts.erb"
178   owner "root"
179   group "root"
180   mode 0o644
181 end
182
183 service "systemd-resolved" do
184   action [:enable, :start]
185 end
186
187 directory "/etc/systemd/resolved.conf.d" do
188   owner "root"
189   group "root"
190   mode 0o755
191 end
192
193 template "/etc/systemd/resolved.conf.d/99-chef.conf" do
194   source "resolved.conf.erb"
195   owner "root"
196   group "root"
197   mode 0o644
198   notifies :restart, "service[systemd-resolved]"
199 end
200
201 if node[:networking][:tcp_fastopen_key]
202   fastopen_keys = data_bag_item("networking", "fastopen")
203
204   node.normal[:sysctl][:tcp_fastopen] = {
205     :comment => "Set shared key for TCP fast open",
206     :parameters => {
207       "net.ipv4.tcp_fastopen_key" => fastopen_keys[node[:networking][:tcp_fastopen_key]]
208     }
209   }
210 end
211
212 node.interfaces(:role => :internal) do |interface|
213   if interface[:gateway] && interface[:gateway] != interface[:address]
214     search(:node, "networking_interfaces*address:#{interface[:gateway]}") do |gateway|
215       next unless gateway[:openvpn]
216
217       gateway[:openvpn][:tunnels].each_value do |tunnel|
218         if tunnel[:peer][:address] # ~FC023
219           route tunnel[:peer][:address] do
220             netmask "255.255.255.255"
221             gateway interface[:gateway]
222             device interface[:interface]
223           end
224         end
225
226         next unless tunnel[:peer][:networks]
227
228         tunnel[:peer][:networks].each do |network|
229           route network[:address] do
230             netmask network[:netmask]
231             gateway interface[:gateway]
232             device interface[:interface]
233           end
234         end
235       end
236     end
237   end
238 end
239
240 zones = {}
241
242 search(:node, "networking:interfaces").collect do |n|
243   next if n[:fqdn] == node[:fqdn]
244
245   n.interfaces.each do |interface|
246     next unless interface[:role] == "external" && interface[:zone]
247
248     zones[interface[:zone]] ||= {}
249     zones[interface[:zone]][interface[:family]] ||= []
250     zones[interface[:zone]][interface[:family]] << interface[:address]
251   end
252 end
253
254 package "shorewall"
255
256 template "/etc/default/shorewall" do
257   source "shorewall-default.erb"
258   owner "root"
259   group "root"
260   mode 0o644
261   notifies :restart, "service[shorewall]"
262 end
263
264 template "/etc/shorewall/shorewall.conf" do
265   source "shorewall.conf.erb"
266   owner "root"
267   group "root"
268   mode 0o644
269   notifies :restart, "service[shorewall]"
270 end
271
272 template "/etc/shorewall/zones" do
273   source "shorewall-zones.erb"
274   owner "root"
275   group "root"
276   mode 0o644
277   variables :type => "ipv4"
278   notifies :restart, "service[shorewall]"
279 end
280
281 template "/etc/shorewall/interfaces" do
282   source "shorewall-interfaces.erb"
283   owner "root"
284   group "root"
285   mode 0o644
286   notifies :restart, "service[shorewall]"
287 end
288
289 template "/etc/shorewall/hosts" do
290   source "shorewall-hosts.erb"
291   owner "root"
292   group "root"
293   mode 0o644
294   variables :zones => zones
295   notifies :restart, "service[shorewall]"
296 end
297
298 template "/etc/shorewall/conntrack" do
299   source "shorewall-conntrack.erb"
300   owner "root"
301   group "root"
302   mode 0o644
303   notifies :restart, "service[shorewall]"
304   only_if { node[:networking][:firewall][:raw] }
305 end
306
307 template "/etc/shorewall/policy" do
308   source "shorewall-policy.erb"
309   owner "root"
310   group "root"
311   mode 0o644
312   notifies :restart, "service[shorewall]"
313 end
314
315 template "/etc/shorewall/rules" do
316   source "shorewall-rules.erb"
317   owner "root"
318   group "root"
319   mode 0o644
320   variables :family => "inet"
321   notifies :restart, "service[shorewall]"
322 end
323
324 service "shorewall" do
325   action [:enable, :start]
326   supports :restart => true
327   status_command "shorewall status"
328 end
329
330 template "/etc/logrotate.d/shorewall" do
331   source "logrotate.shorewall.erb"
332   owner "root"
333   group "root"
334   mode 0o644
335   variables :name => "shorewall"
336 end
337
338 firewall_rule "limit-icmp-echo" do
339   action :accept
340   family :inet
341   source "net"
342   dest "fw"
343   proto "icmp"
344   dest_ports "echo-request"
345   rate_limit "s:1/sec:5"
346 end
347
348 %w[ucl ams bm].each do |zone|
349   firewall_rule "accept-openvpn-#{zone}" do
350     action :accept
351     source zone
352     dest "fw"
353     proto "udp"
354     dest_ports "1194:1197"
355     source_ports "1194:1197"
356   end
357 end
358
359 if node[:roles].include?("gateway")
360   template "/etc/shorewall/masq" do
361     source "shorewall-masq.erb"
362     owner "root"
363     group "root"
364     mode 0o644
365     notifies :restart, "service[shorewall]"
366   end
367 else
368   file "/etc/shorewall/masq" do
369     action :delete
370     notifies :restart, "service[shorewall]"
371   end
372 end
373
374 unless node.interfaces(:family => :inet6).empty?
375   package "shorewall6"
376
377   template "/etc/default/shorewall6" do
378     source "shorewall-default.erb"
379     owner "root"
380     group "root"
381     mode 0o644
382     notifies :restart, "service[shorewall6]"
383   end
384
385   template "/etc/shorewall6/shorewall6.conf" do
386     source "shorewall6.conf.erb"
387     owner "root"
388     group "root"
389     mode 0o644
390     notifies :restart, "service[shorewall6]"
391   end
392
393   template "/etc/shorewall6/zones" do
394     source "shorewall-zones.erb"
395     owner "root"
396     group "root"
397     mode 0o644
398     variables :type => "ipv6"
399     notifies :restart, "service[shorewall6]"
400   end
401
402   template "/etc/shorewall6/interfaces" do
403     source "shorewall6-interfaces.erb"
404     owner "root"
405     group "root"
406     mode 0o644
407     notifies :restart, "service[shorewall6]"
408   end
409
410   template "/etc/shorewall6/hosts" do
411     source "shorewall6-hosts.erb"
412     owner "root"
413     group "root"
414     mode 0o644
415     variables :zones => zones
416     notifies :restart, "service[shorewall6]"
417   end
418
419   template "/etc/shorewall6/conntrack" do
420     source "shorewall-conntrack.erb"
421     owner "root"
422     group "root"
423     mode 0o644
424     notifies :restart, "service[shorewall6]"
425     only_if { node[:networking][:firewall][:raw] }
426   end
427
428   template "/etc/shorewall6/policy" do
429     source "shorewall-policy.erb"
430     owner "root"
431     group "root"
432     mode 0o644
433     notifies :restart, "service[shorewall6]"
434   end
435
436   template "/etc/shorewall6/rules" do
437     source "shorewall-rules.erb"
438     owner "root"
439     group "root"
440     mode 0o644
441     variables :family => "inet6"
442     notifies :restart, "service[shorewall6]"
443   end
444
445   service "shorewall6" do
446     action [:enable, :start]
447     supports :restart => true
448     status_command "shorewall6 status"
449   end
450
451   template "/etc/logrotate.d/shorewall6" do
452     source "logrotate.shorewall.erb"
453     owner "root"
454     group "root"
455     mode 0o644
456     variables :name => "shorewall6"
457   end
458
459   firewall_rule "limit-icmp6-echo" do
460     action :accept
461     family :inet6
462     source "net"
463     dest "fw"
464     proto "ipv6-icmp"
465     dest_ports "echo-request"
466     rate_limit "s:1/sec:5"
467   end
468 end
469
470 firewall_rule "accept-http" do
471   action :accept
472   source "net"
473   dest "fw"
474   proto "tcp:syn"
475   dest_ports "http"
476   rate_limit node[:networking][:firewall][:http_rate_limit]
477   connection_limit node[:networking][:firewall][:http_connection_limit]
478 end
479
480 firewall_rule "accept-https" do
481   action :accept
482   source "net"
483   dest "fw"
484   proto "tcp:syn"
485   dest_ports "https"
486   rate_limit node[:networking][:firewall][:http_rate_limit]
487   connection_limit node[:networking][:firewall][:http_connection_limit]
488 end