construqt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/construqt/addresses.rb +204 -0
- data/lib/construqt/bgps.rb +164 -0
- data/lib/construqt/cables.rb +47 -0
- data/lib/construqt/firewalls.rb +247 -0
- data/lib/construqt/flavour/ciscian/ciscian.rb +687 -0
- data/lib/construqt/flavour/ciscian/dialect_dlink-dgs15xx.rb +235 -0
- data/lib/construqt/flavour/ciscian/dialect_hp-2510g.rb +114 -0
- data/lib/construqt/flavour/delegates.rb +448 -0
- data/lib/construqt/flavour/flavour.rb +97 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik.rb +417 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_bgp.rb +134 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_interface.rb +79 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_ipsec.rb +65 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_result.rb +182 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_schema.rb +355 -0
- data/lib/construqt/flavour/plantuml/plantuml.rb +462 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu.rb +381 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_bgp.rb +117 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_dns.rb +97 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb +300 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_ipsec.rb +144 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_opvn.rb +60 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_result.rb +537 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_services.rb +115 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_vrrp.rb +52 -0
- data/lib/construqt/flavour/unknown/unknown.rb +175 -0
- data/lib/construqt/hostid.rb +42 -0
- data/lib/construqt/hosts.rb +98 -0
- data/lib/construqt/interfaces.rb +166 -0
- data/lib/construqt/ipsecs.rb +64 -0
- data/lib/construqt/networks.rb +81 -0
- data/lib/construqt/regions.rb +32 -0
- data/lib/construqt/resource.rb +42 -0
- data/lib/construqt/services.rb +53 -0
- data/lib/construqt/tags.rb +61 -0
- data/lib/construqt/templates.rb +37 -0
- data/lib/construqt/tests/test_addresses.rb +50 -0
- data/lib/construqt/tests/test_bgps.rb +24 -0
- data/lib/construqt/tests/test_hostid.rb +32 -0
- data/lib/construqt/tests/test_hosts.rb +23 -0
- data/lib/construqt/tests/test_utils.rb +76 -0
- data/lib/construqt/users.rb +19 -0
- data/lib/construqt/util.rb +163 -0
- data/lib/construqt/version.rb +3 -0
- data/lib/construqt/vlans.rb +51 -0
- data/lib/construqt.rb +92 -0
- metadata +105 -0
@@ -0,0 +1,381 @@
|
|
1
|
+
|
2
|
+
require_relative 'flavour_ubuntu_dns.rb'
|
3
|
+
require_relative 'flavour_ubuntu_ipsec.rb'
|
4
|
+
require_relative 'flavour_ubuntu_bgp.rb'
|
5
|
+
require_relative 'flavour_ubuntu_opvn.rb'
|
6
|
+
require_relative 'flavour_ubuntu_vrrp.rb'
|
7
|
+
require_relative 'flavour_ubuntu_firewall.rb'
|
8
|
+
require_relative 'flavour_ubuntu_result.rb'
|
9
|
+
require_relative 'flavour_ubuntu_services.rb'
|
10
|
+
|
11
|
+
module Construqt
|
12
|
+
module Flavour
|
13
|
+
module Ubuntu
|
14
|
+
def self.name
|
15
|
+
'ubuntu'
|
16
|
+
end
|
17
|
+
|
18
|
+
Flavour.add(self)
|
19
|
+
|
20
|
+
# class Interface < OpenStruct
|
21
|
+
# def initialize(cfg)
|
22
|
+
# super(cfg)
|
23
|
+
# end
|
24
|
+
|
25
|
+
# def build_config(host, iface)
|
26
|
+
# self.clazz.build_config(host, iface||self)
|
27
|
+
# end
|
28
|
+
|
29
|
+
# end
|
30
|
+
|
31
|
+
class Device < OpenStruct
|
32
|
+
def initialize(cfg)
|
33
|
+
super(cfg)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.add_address(host, ifname, iface, lines, writer)
|
37
|
+
if iface.address.nil?
|
38
|
+
Firewall.create(host, ifname, iface)
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
writer.header.mode(EtcNetworkInterfaces::Entry::Header::MODE_DHCP) if iface.address.dhcpv4?
|
43
|
+
writer.header.mode(EtcNetworkInterfaces::Entry::Header::MODE_LOOPBACK) if iface.address.loopback?
|
44
|
+
lines.add(iface.flavour) if iface.flavour
|
45
|
+
iface.address.ips.each do |ip|
|
46
|
+
lines.up("ip addr add #{ip.to_string} dev #{ifname}")
|
47
|
+
lines.down("ip addr del #{ip.to_string} dev #{ifname}")
|
48
|
+
end
|
49
|
+
|
50
|
+
iface.address.routes.each do |route|
|
51
|
+
if route.metric
|
52
|
+
metric = " metric #{route.metric}"
|
53
|
+
else
|
54
|
+
metric = ""
|
55
|
+
end
|
56
|
+
lines.up("ip route add #{route.dst.to_string} via #{route.via.to_s}#{metric}")
|
57
|
+
lines.down("ip route del #{route.dst.to_string} via #{route.via.to_s}#{metric}")
|
58
|
+
end
|
59
|
+
|
60
|
+
Firewall.create(host, ifname, iface)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_config(host, iface)
|
64
|
+
self.class.build_config(host, iface)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.add_services(host, ifname, iface, writer)
|
68
|
+
iface.services && iface.services.each do |service|
|
69
|
+
Services.get_renderer(service).interfaces(host, ifname, iface, writer)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.build_config(host, iface)
|
74
|
+
# binding.pry
|
75
|
+
writer = host.result.etc_network_interfaces.get(iface)
|
76
|
+
writer.header.protocol(EtcNetworkInterfaces::Entry::Header::PROTO_INET4)
|
77
|
+
#binding.pry #unless iface.delegate
|
78
|
+
writer.lines.add(iface.delegate.flavour) if iface.delegate.flavour
|
79
|
+
ifname = writer.header.get_interface_name
|
80
|
+
# ifaces.header.mode(Result::EtcNetworkInterfaces::Entry::Header::MODE_DHCP4) if iface.address.dhcpv4?
|
81
|
+
# ifaces.header.mode(Result::EtcNetworkInterfaces::Entry::Header::MODE_LOOOPBACK) if iface.address.loopback?
|
82
|
+
writer.lines.up("ip link set mtu #{iface.delegate.mtu} dev #{ifname} up")
|
83
|
+
writer.lines.down("ip link set dev #{ifname} down")
|
84
|
+
add_address(host, ifname, iface.delegate, writer.lines, writer) #unless iface.address.nil? || iface.address.ips.empty?
|
85
|
+
add_services(host, ifname, iface.delegate, writer)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Bond < OpenStruct
|
90
|
+
def initialize(cfg)
|
91
|
+
super(cfg)
|
92
|
+
end
|
93
|
+
|
94
|
+
def build_config(host, bond)
|
95
|
+
bond_delegate = bond.delegate
|
96
|
+
bond_delegate.interfaces.each do |i|
|
97
|
+
host.result.etc_network_interfaces.get(i).lines.add("bond-master #{bond_delegate.name}")
|
98
|
+
end
|
99
|
+
|
100
|
+
mac_address = bond_delegate.mac_address || Construqt::Util.generate_mac_address_from_name("#{host.name} #{bond_delegate.name}")
|
101
|
+
host.result.etc_network_interfaces.get(bond_delegate).lines.add(<<BOND)
|
102
|
+
pre-up ip link set dev #{bond_delegate.name} mtu #{bond_delegate.mtu} address #{mac_address}
|
103
|
+
bond-mode #{bond_delegate.mode||'active-backup'}
|
104
|
+
bond-miimon 100
|
105
|
+
bond-lacp-rate 1
|
106
|
+
bond-slaves none
|
107
|
+
BOND
|
108
|
+
Device.build_config(host, bond)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class Vlan < OpenStruct
|
113
|
+
def initialize(cfg)
|
114
|
+
super(cfg)
|
115
|
+
end
|
116
|
+
|
117
|
+
def build_config(host, iface)
|
118
|
+
vlan = iface.name.split('.')
|
119
|
+
throw "vlan name not valid if.# => #{iface.name}" if vlan.length != 2 ||
|
120
|
+
!vlan.first.match(/^[0-9a-zA-Z]+$/) ||
|
121
|
+
!vlan.last.match(/^[0-9]+/) ||
|
122
|
+
!(1 <= vlan.last.to_i && vlan.last.to_i < 4096)
|
123
|
+
Device.build_config(host, iface)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class Bridge < OpenStruct
|
128
|
+
def initialize(cfg)
|
129
|
+
super(cfg)
|
130
|
+
end
|
131
|
+
|
132
|
+
def build_config(host, iface)
|
133
|
+
port_list = iface.interfaces.map { |i| i.name }.join(",")
|
134
|
+
host.result.etc_network_interfaces.get(iface).lines.add("bridge_ports #{port_list}")
|
135
|
+
Device.build_config(host, iface)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class Host < OpenStruct
|
140
|
+
def initialize(cfg)
|
141
|
+
super(cfg)
|
142
|
+
end
|
143
|
+
|
144
|
+
def build_config(host, unused)
|
145
|
+
host.result.add(self, <<SCTL, Construqt::Resources::Rights::ROOT_0644, "etc", "sysctl.conf")
|
146
|
+
net.ipv4.conf.all.forwarding = 1
|
147
|
+
net.ipv4.conf.default.forwarding = 1
|
148
|
+
net.ipv4.vs.pmtu_disc=1
|
149
|
+
|
150
|
+
net.ipv6.conf.all.autoconf=0
|
151
|
+
net.ipv6.conf.all.accept_ra=0
|
152
|
+
net.ipv6.conf.all.forwarding=1
|
153
|
+
SCTL
|
154
|
+
host.result.add(self, <<HOSTS, Construqt::Resources::Rights::ROOT_0644, "etc", "hosts")
|
155
|
+
127.0.0.1 localhost
|
156
|
+
::1 localhost ip6-localhost ip6-loopback
|
157
|
+
fe00::0 ip6-localnet
|
158
|
+
ff00::0 ip6-mcastprefix
|
159
|
+
ff02::1 ip6-allnodes
|
160
|
+
ff02::2 ip6-allrouters
|
161
|
+
|
162
|
+
127.0.1.1 #{host.name} #{host.region.network.fqdn(host.name)}
|
163
|
+
HOSTS
|
164
|
+
host.result.add(self, host.name, Construqt::Resources::Rights::ROOT_0644, "etc", "hostname")
|
165
|
+
host.result.add(self, "# WTF resolvconf", Construqt::Resources::Rights::ROOT_0644, "etc", "resolvconf", "resolv.conf.d", "orignal");
|
166
|
+
host.result.add(self,
|
167
|
+
(host.region.network.dns_resolver.nameservers.ips.map{|i| "nameserver #{i.to_s}" }+
|
168
|
+
["search #{host.region.network.dns_resolver.search.join(' ')}"]).join("\n"),
|
169
|
+
Construqt::Resources::Rights::ROOT_0644, "etc", "resolv.conf")
|
170
|
+
#binding.pry
|
171
|
+
Dns.build_config(host) if host.delegate.dns_server
|
172
|
+
akeys = []
|
173
|
+
ykeys = []
|
174
|
+
skeys = []
|
175
|
+
host.region.users.all.each do |u|
|
176
|
+
akeys << u.public_key if u.public_key
|
177
|
+
ykeys << "#{u.name}:#{u.yubikey}" if u.yubikey
|
178
|
+
skeys << "#{u.shadow}" if u.shadow
|
179
|
+
end
|
180
|
+
|
181
|
+
host.result.add(self, skeys.join(), Construqt::Resources::Rights::ROOT_0644, "etc", "shadow.merge")
|
182
|
+
host.result.add(self, akeys.join(), Construqt::Resources::Rights::ROOT_0644, "root", ".ssh", "authorized_keys")
|
183
|
+
host.result.add(self, ykeys.join("\n"), Construqt::Resources::Rights::ROOT_0644, "etc", "yubikey_mappings")
|
184
|
+
|
185
|
+
host.result.add(self, <<SSH , Construqt::Resources::Rights::ROOT_0644, "etc", "ssh", "sshd_config")
|
186
|
+
# Package generated configuration file
|
187
|
+
# See the sshd_config(5) manpage for details
|
188
|
+
|
189
|
+
# What ports, IPs and protocols we listen for
|
190
|
+
Port 22
|
191
|
+
# Use these options to restrict which interfaces/protocols sshd will bind to
|
192
|
+
#ListenAddress ::
|
193
|
+
#ListenAddress 0.0.0.0
|
194
|
+
Protocol 2
|
195
|
+
# HostKeys for protocol version 2
|
196
|
+
HostKey /etc/ssh/ssh_host_rsa_key
|
197
|
+
HostKey /etc/ssh/ssh_host_dsa_key
|
198
|
+
HostKey /etc/ssh/ssh_host_ecdsa_key
|
199
|
+
HostKey /etc/ssh/ssh_host_ed25519_key
|
200
|
+
#Privilege Separation is turned on for security
|
201
|
+
UsePrivilegeSeparation yes
|
202
|
+
|
203
|
+
# Lifetime and size of ephemeral version 1 server key
|
204
|
+
KeyRegenerationInterval 3600
|
205
|
+
ServerKeyBits 1024
|
206
|
+
|
207
|
+
# Logging
|
208
|
+
SyslogFacility AUTH
|
209
|
+
LogLevel INFO
|
210
|
+
|
211
|
+
# Authentication:
|
212
|
+
LoginGraceTime 120
|
213
|
+
PermitRootLogin without-password
|
214
|
+
StrictModes yes
|
215
|
+
|
216
|
+
RSAAuthentication yes
|
217
|
+
PubkeyAuthentication yes
|
218
|
+
#AuthorizedKeysFile %h/.ssh/authorized_keys
|
219
|
+
|
220
|
+
# Don't read the user's ~/.rhosts and ~/.shosts files
|
221
|
+
IgnoreRhosts yes
|
222
|
+
# For this to work you will also need host keys in /etc/ssh_known_hosts
|
223
|
+
RhostsRSAAuthentication no
|
224
|
+
# similar for protocol version 2
|
225
|
+
HostbasedAuthentication no
|
226
|
+
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
|
227
|
+
#IgnoreUserKnownHosts yes
|
228
|
+
|
229
|
+
# To enable empty passwords, change to yes (NOT RECOMMENDED)
|
230
|
+
PermitEmptyPasswords no
|
231
|
+
|
232
|
+
# Change to yes to enable challenge-response passwords (beware issues with
|
233
|
+
# some PAM modules and threads)
|
234
|
+
ChallengeResponseAuthentication no
|
235
|
+
|
236
|
+
# Change to no to disable tunnelled clear text passwords
|
237
|
+
PasswordAuthentication no
|
238
|
+
|
239
|
+
# Kerberos options
|
240
|
+
#KerberosAuthentication no
|
241
|
+
#KerberosGetAFSToken no
|
242
|
+
#KerberosOrLocalPasswd yes
|
243
|
+
#KerberosTicketCleanup yes
|
244
|
+
|
245
|
+
# GSSAPI options
|
246
|
+
#GSSAPIAuthentication no
|
247
|
+
#GSSAPICleanupCredentials yes
|
248
|
+
|
249
|
+
X11Forwarding yes
|
250
|
+
X11DisplayOffset 10
|
251
|
+
PrintMotd no
|
252
|
+
PrintLastLog yes
|
253
|
+
TCPKeepAlive yes
|
254
|
+
#UseLogin no
|
255
|
+
|
256
|
+
#MaxStartups 10:30:60
|
257
|
+
#Banner /etc/issue.net
|
258
|
+
|
259
|
+
# Allow client to pass locale environment variables
|
260
|
+
AcceptEnv LANG LC_*
|
261
|
+
|
262
|
+
Subsystem sftp /usr/lib/openssh/sftp-server
|
263
|
+
|
264
|
+
# Set this to 'yes' to enable PAM authentication, account processing,
|
265
|
+
# and session processing. If this is enabled, PAM authentication will
|
266
|
+
# be allowed through the ChallengeResponseAuthentication and
|
267
|
+
# PasswordAuthentication. Depending on your PAM configuration,
|
268
|
+
# PAM authentication via ChallengeResponseAuthentication may bypass
|
269
|
+
# the setting of "PermitRootLogin without-password".
|
270
|
+
# If you just want the PAM account and session checks to run without
|
271
|
+
# PAM authentication, then enable this but set PasswordAuthentication
|
272
|
+
# and ChallengeResponseAuthentication to 'no'.
|
273
|
+
UsePAM yes
|
274
|
+
SSH
|
275
|
+
host.result.add(self, <<PAM , Construqt::Resources::Rights::ROOT_0644, "etc", "pam.d", "openvpn")
|
276
|
+
#{host.delegate.yubikey ? '':'# '}auth required pam_yubico.so id=16 authfile=/etc/yubikey_mappings
|
277
|
+
auth [success=1 default=ignore] pam_unix.so nullok_secure try_first_pass
|
278
|
+
auth requisite pam_deny.so
|
279
|
+
|
280
|
+
@include common-account
|
281
|
+
@include common-session-noninteractive
|
282
|
+
PAM
|
283
|
+
#binding.pry
|
284
|
+
host.delegate.files && host.delegate.files.each do |file|
|
285
|
+
if host.result.replace(nil, file.data, file.right, *file.path)
|
286
|
+
Construqt.logger.warn("the file #{file.path} was overriden!")
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
class Gre < OpenStruct
|
293
|
+
def initialize(cfg)
|
294
|
+
super(cfg)
|
295
|
+
end
|
296
|
+
|
297
|
+
def build_config(host, gre)
|
298
|
+
gre_delegate = gre.delegate
|
299
|
+
# binding.pry
|
300
|
+
cfg = nil
|
301
|
+
if gre_delegate.local.first_ipv6
|
302
|
+
cfg = OpenStruct.new(:prefix=>6, :my=>gre_delegate.local.first_ipv6, :other => gre_delegate.remote.first_ipv6, :mode => "ip6gre")
|
303
|
+
elsif gre_delegate.local.first_ipv4
|
304
|
+
cfg = OpenStruct.new(:prefix=>4, :my=>gre_delegate.local.first_ipv4, :other => gre_delegate.remote.first_ipv4, :mode => "ipgre")
|
305
|
+
end
|
306
|
+
|
307
|
+
throw "need a local address #{host.name}:#{gre_delegate.name}" unless cfg
|
308
|
+
local_iface = host.interfaces.values.find { |iface| iface.address.match_network(cfg.my) }
|
309
|
+
throw "need a interface with address #{host.name}:#{cfg.my}" unless local_iface
|
310
|
+
iname = Util.clean_if("gt#{cfg.prefix}", gre_delegate.name)
|
311
|
+
|
312
|
+
writer_local = host.result.etc_network_interfaces.get(local_iface)
|
313
|
+
writer_local.lines.up("/bin/bash /etc/network/#{iname}-up.iface")
|
314
|
+
writer_local.lines.down("/bin/bash /etc/network/#{iname}-down.iface")
|
315
|
+
|
316
|
+
|
317
|
+
writer = host.result.etc_network_interfaces.get(gre_delegate)
|
318
|
+
writer.skip_interfaces.header.interface_name(iname)
|
319
|
+
writer.lines.up("ip -#{cfg.prefix} tunnel add #{iname} mode #{cfg.mode} local #{cfg.my.to_s} remote #{cfg.other.to_s}")
|
320
|
+
# writer.lines.up("ip -#{cfg.prefix} link set dev #{iname} up")
|
321
|
+
Device.build_config(host, gre)
|
322
|
+
# Device.add_address(host, iname, iface, writer.lines, writer)
|
323
|
+
writer.lines.down("ip -#{cfg.prefix} tunnel del #{iname}")
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
class Template < OpenStruct
|
328
|
+
def initialize(cfg)
|
329
|
+
super(cfg)
|
330
|
+
end
|
331
|
+
|
332
|
+
def build_config(host, iface)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def self.clazzes
|
337
|
+
{
|
338
|
+
"opvn" => Opvn,
|
339
|
+
"gre" => Gre,
|
340
|
+
"host" => Host,
|
341
|
+
"device"=> Device,
|
342
|
+
"vrrp" => Vrrp,
|
343
|
+
"bridge" => Bridge,
|
344
|
+
"bond" => Bond,
|
345
|
+
"vlan" => Vlan,
|
346
|
+
"result" => Result,
|
347
|
+
"ipsec" => Ipsec,
|
348
|
+
"bgp" => Bgp,
|
349
|
+
"template" => Template
|
350
|
+
}
|
351
|
+
end
|
352
|
+
|
353
|
+
def self.clazz(name)
|
354
|
+
ret = self.clazzes[name]
|
355
|
+
throw "class not found #{name}" unless ret
|
356
|
+
ret
|
357
|
+
end
|
358
|
+
|
359
|
+
def self.create_host(name, cfg)
|
360
|
+
cfg['name'] = name
|
361
|
+
cfg['result'] = nil
|
362
|
+
host = Host.new(cfg)
|
363
|
+
host.result = Result.new(host)
|
364
|
+
host
|
365
|
+
end
|
366
|
+
|
367
|
+
def self.create_interface(name, cfg)
|
368
|
+
cfg['name'] = name
|
369
|
+
clazz(cfg['clazz']).new(cfg)
|
370
|
+
end
|
371
|
+
|
372
|
+
def self.create_bgp(cfg)
|
373
|
+
Bgp.new(cfg)
|
374
|
+
end
|
375
|
+
|
376
|
+
def self.create_ipsec(cfg)
|
377
|
+
Ipsec.new(cfg)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module Construqt
|
2
|
+
module Flavour
|
3
|
+
module Ubuntu
|
4
|
+
|
5
|
+
class Bgp < OpenStruct
|
6
|
+
def initialize(cfg)
|
7
|
+
super(cfg)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.header(host)
|
11
|
+
addrs = {}
|
12
|
+
host.interfaces.values.each do |iface|
|
13
|
+
iface = iface.delegate
|
14
|
+
next unless iface.cfg
|
15
|
+
next unless iface.cfg.kind_of? Construqt::Bgp
|
16
|
+
addrs[iface.name] = iface
|
17
|
+
end
|
18
|
+
return if addrs.empty?
|
19
|
+
bird_v4 = self.header_bird(host, OpenStruct.new(:net_clazz => IPAddress::IPv4, :filter => lambda {|ip| ip.ipv4? }))
|
20
|
+
host.result.add(self, bird_v4, Construqt::Resources::Rights::ROOT_0644, "etc", "bird", "bird.conf")
|
21
|
+
bird_v6 = self.header_bird(host, OpenStruct.new(:net_clazz => IPAddress::IPv6, :filter => lambda {|ip| ip.ipv6? }))
|
22
|
+
host.result.add(self, bird_v6, Construqt::Resources::Rights::ROOT_0644, "etc", "bird", "bird6.conf")
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.header_bird(host, mode)
|
26
|
+
# binding.pry
|
27
|
+
ret = <<BGP
|
28
|
+
log syslog { debug, trace, info, remote, warning, error, auth, fatal, bug };
|
29
|
+
router id #{host.id.first_ipv4.first_ipv4.to_s};
|
30
|
+
protocol device {
|
31
|
+
}
|
32
|
+
protocol direct {
|
33
|
+
}
|
34
|
+
protocol kernel {
|
35
|
+
learn;
|
36
|
+
persist; # Don't remove routes on bird shutdown
|
37
|
+
scan time 20; # Scan kernel routing table every 20 seconds
|
38
|
+
export all; # Default is export none
|
39
|
+
}
|
40
|
+
protocol static {
|
41
|
+
}
|
42
|
+
|
43
|
+
BGP
|
44
|
+
Bgps.filters.each do |filter|
|
45
|
+
ret = ret + "filter filter_#{filter.name} {\n"
|
46
|
+
filter.list.each do |rule|
|
47
|
+
nets = rule['network']
|
48
|
+
if nets.kind_of?(String)
|
49
|
+
nets = Construqt::Tags.find(nets, mode.net_clazz)
|
50
|
+
# puts ">>>>>>>>>> #{nets.map{|i| i.class.name}}"
|
51
|
+
nets = IPAddress::summarize(nets)
|
52
|
+
else
|
53
|
+
nets = nets.ips
|
54
|
+
end
|
55
|
+
|
56
|
+
nets.each do |ip|
|
57
|
+
next unless mode.filter.call(ip)
|
58
|
+
ip_str = ip.to_string
|
59
|
+
if rule['prefix_length']
|
60
|
+
ip_str = "#{ip.to_string}{#{rule['prefix_length'].first},#{rule['prefix_length'].last}}"
|
61
|
+
end
|
62
|
+
|
63
|
+
ret = ret + " if net ~ [ #{ip_str} ] then { print \"#{rule['rule']}:\",net; #{rule['rule']}; }\n"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
ret = ret + "}\n\n"
|
68
|
+
end
|
69
|
+
|
70
|
+
ret
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_bird_conf
|
74
|
+
if self.my.address.first_ipv4 && self.other.my.address.first_ipv4
|
75
|
+
self.my.host.result.add(self, <<BGP, Construqt::Resources::Rights::ROOT_0644, "etc", "bird", "bird.conf")
|
76
|
+
protocol bgp #{Util.clean_bgp(self.my.host.name)}_#{Util.clean_bgp(self.other.host.name)} {
|
77
|
+
description "#{self.my.host.name} <=> #{self.other.host.name}";
|
78
|
+
direct;
|
79
|
+
next hop self;
|
80
|
+
#{self.as == self.other.as ? '' : '#'}rr client;
|
81
|
+
local #{self.my.address.first_ipv4} as #{self.as.num};
|
82
|
+
neighbor #{self.other.my.address.first_ipv4} as #{self.other.as.num};
|
83
|
+
password "#{Util.password(self.cfg.password)}";
|
84
|
+
import #{self.filter['in'] ? "filter filter_"+self.filter['in'].name : "all"};
|
85
|
+
export #{self.filter['out'] ? "filter filter_"+self.filter['out'].name : "all"};
|
86
|
+
}
|
87
|
+
BGP
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def build_bird6_conf
|
92
|
+
# binding.pry
|
93
|
+
if self.my.address.first_ipv6 && self.other.my.address.first_ipv6
|
94
|
+
self.my.host.result.add(self, <<BGP, Construqt::Resources::Rights::ROOT_0644, "etc", "bird", "bird6.conf")
|
95
|
+
protocol bgp #{Util.clean_bgp(self.my.host.name)}_#{Util.clean_bgp(self.other.host.name)} {
|
96
|
+
description "#{self.my.host.name} <=> #{self.other.host.name}";
|
97
|
+
direct;
|
98
|
+
next hop self;
|
99
|
+
#{self.as == self.other.as ? '' : '#'}rr client;
|
100
|
+
local as #{self.as.num};
|
101
|
+
neighbor #{self.other.my.address.first_ipv6} as #{self.other.as.num};
|
102
|
+
password "#{Util.password(self.cfg.password)}";
|
103
|
+
import #{self.filter['in'] ? "filter filter_"+self.filter['in'].name : "all"};
|
104
|
+
export #{self.filter['out'] ? "filter filter_"+self.filter['out'].name : "all"};
|
105
|
+
}
|
106
|
+
BGP
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def build_config(unused, unused1)
|
111
|
+
build_bird_conf
|
112
|
+
build_bird6_conf
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Construqt
|
2
|
+
module Flavour
|
3
|
+
|
4
|
+
module Ubuntu
|
5
|
+
module Dns
|
6
|
+
|
7
|
+
def self.write_header(region, domain)
|
8
|
+
ret = [<<OUT]
|
9
|
+
; this is a generated file do not edit!!!!!
|
10
|
+
; for #{domain.to_s}
|
11
|
+
$TTL 86400 ; 1 day
|
12
|
+
#{domain}. IN SOA ns.#{region.network.domain}. #{region.network.contact}. (
|
13
|
+
#{Time.now.to_i} ; serial
|
14
|
+
10000 ; refresh (2 hours 46 minutes 40 seconds)
|
15
|
+
3600 ; retry (1 hour)
|
16
|
+
604800 ; expire (1 week)
|
17
|
+
28800 ; minimum (8 hours)
|
18
|
+
)
|
19
|
+
OUT
|
20
|
+
region.hosts.get_hosts.each do |host|
|
21
|
+
next unless host.delegate.dns_server
|
22
|
+
plain_adr = region.network.addresses.all.find{|i| i.name! == host.name }
|
23
|
+
unless plain_adr
|
24
|
+
plain_adr = host.id.first_ipv6
|
25
|
+
end
|
26
|
+
|
27
|
+
binding.pry unless plain_adr.name
|
28
|
+
|
29
|
+
ret << "#{domain}. 3600 IN NS #{region.network.fqdn(plain_adr.name)}."
|
30
|
+
#if (domain == Addresses.domain)
|
31
|
+
# ret << "#{host.id.first_ipv6.fqdn}. 3600 IN A #{host.id.first_ipv4}" if host.id.first_ipv4
|
32
|
+
# ret << "#{host.id.first_ipv6.fqdn}. 3600 IN AAAA #{host.id.first_ipv6}" if host.id.first_ipv6
|
33
|
+
#end
|
34
|
+
end
|
35
|
+
|
36
|
+
ret << ""
|
37
|
+
ret.join("\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.build_config(host)
|
41
|
+
forward = {}
|
42
|
+
reverse = {}
|
43
|
+
host.region.network.addresses.all.each do |address|
|
44
|
+
next unless address
|
45
|
+
next if address.ips.empty?
|
46
|
+
unless address.name!
|
47
|
+
Construqt.logger.warn "unreference address #{address.ips.map{|i| i.to_string}}"
|
48
|
+
next
|
49
|
+
end
|
50
|
+
name = host.region.network.fqdn(address.name!)
|
51
|
+
domain = host.region.network.domain
|
52
|
+
forward[domain] ||= []
|
53
|
+
address.ips.each do |ip|
|
54
|
+
next if ip.to_i == ip.network.to_i && ((ip.ipv6? && ip.prefix < 128) || (ip.ipv4? && ip.prefix < 32))
|
55
|
+
forward[domain] << "#{"%-42s" % "#{name}."} 3600 IN #{ip.ipv4? ? 'A' : 'AAAA'} #{ip.to_s}"
|
56
|
+
if ip.ipv4?
|
57
|
+
forward[domain] << "#{"ipv4-%-37s" % "#{name}."} 3600 IN A #{ip.to_s}"
|
58
|
+
end
|
59
|
+
|
60
|
+
if ip.ipv6?
|
61
|
+
forward[domain] << "#{"ipv6-%-37s" % "#{name}."} 3600 IN AAAA #{ip.to_s}"
|
62
|
+
end
|
63
|
+
|
64
|
+
network = host.region.network.to_network(ip.network)
|
65
|
+
reverse[network] ||= {}
|
66
|
+
reverse[network][ip.reverse.to_s] ||= "#{ip.reverse} 3600 IN PTR #{name}."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
include = {}
|
71
|
+
forward.each do |domain, lines|
|
72
|
+
include[domain] = "/etc/bind/tables/#{domain}.forward"
|
73
|
+
host.result.add(self, write_header(host.region, domain), Construqt::Resources::Rights::ROOT_0644, "etc/bind/tables", "#{domain}.forward")
|
74
|
+
host.result.add(self, lines.sort.join("\n"), Construqt::Resources::Rights::ROOT_0644, "etc/bind/tables", "#{domain}.forward")
|
75
|
+
end
|
76
|
+
|
77
|
+
reverse.each do |domain, lines|
|
78
|
+
include[domain.rev_domains.first] = "/etc/bind/tables/#{domain}.reverse"
|
79
|
+
host.result.add(self, write_header(host.region, domain.rev_domains.first), Construqt::Resources::Rights::ROOT_0644, "etc/bind/tables", "#{domain.to_s}.reverse")
|
80
|
+
host.result.add(self, lines.values.sort.join("\n"), Construqt::Resources::Rights::ROOT_0644, "etc/bind/tables", "#{domain.to_s}.reverse")
|
81
|
+
end
|
82
|
+
|
83
|
+
include.each do |domain,path|
|
84
|
+
host.result.add(self, <<DNS, Construqt::Resources::Rights::ROOT_0644, "etc/bind/named.conf.local")
|
85
|
+
zone "#{domain.to_s}" {
|
86
|
+
type master;
|
87
|
+
file "#{path}";
|
88
|
+
notify yes;
|
89
|
+
allow-query { any; };
|
90
|
+
};
|
91
|
+
DNS
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|