construqt 0.0.1
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.
- 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
|