construqt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/lib/construqt/addresses.rb +204 -0
  3. data/lib/construqt/bgps.rb +164 -0
  4. data/lib/construqt/cables.rb +47 -0
  5. data/lib/construqt/firewalls.rb +247 -0
  6. data/lib/construqt/flavour/ciscian/ciscian.rb +687 -0
  7. data/lib/construqt/flavour/ciscian/dialect_dlink-dgs15xx.rb +235 -0
  8. data/lib/construqt/flavour/ciscian/dialect_hp-2510g.rb +114 -0
  9. data/lib/construqt/flavour/delegates.rb +448 -0
  10. data/lib/construqt/flavour/flavour.rb +97 -0
  11. data/lib/construqt/flavour/mikrotik/flavour_mikrotik.rb +417 -0
  12. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_bgp.rb +134 -0
  13. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_interface.rb +79 -0
  14. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_ipsec.rb +65 -0
  15. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_result.rb +182 -0
  16. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_schema.rb +355 -0
  17. data/lib/construqt/flavour/plantuml/plantuml.rb +462 -0
  18. data/lib/construqt/flavour/ubuntu/flavour_ubuntu.rb +381 -0
  19. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_bgp.rb +117 -0
  20. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_dns.rb +97 -0
  21. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb +300 -0
  22. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_ipsec.rb +144 -0
  23. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_opvn.rb +60 -0
  24. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_result.rb +537 -0
  25. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_services.rb +115 -0
  26. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_vrrp.rb +52 -0
  27. data/lib/construqt/flavour/unknown/unknown.rb +175 -0
  28. data/lib/construqt/hostid.rb +42 -0
  29. data/lib/construqt/hosts.rb +98 -0
  30. data/lib/construqt/interfaces.rb +166 -0
  31. data/lib/construqt/ipsecs.rb +64 -0
  32. data/lib/construqt/networks.rb +81 -0
  33. data/lib/construqt/regions.rb +32 -0
  34. data/lib/construqt/resource.rb +42 -0
  35. data/lib/construqt/services.rb +53 -0
  36. data/lib/construqt/tags.rb +61 -0
  37. data/lib/construqt/templates.rb +37 -0
  38. data/lib/construqt/tests/test_addresses.rb +50 -0
  39. data/lib/construqt/tests/test_bgps.rb +24 -0
  40. data/lib/construqt/tests/test_hostid.rb +32 -0
  41. data/lib/construqt/tests/test_hosts.rb +23 -0
  42. data/lib/construqt/tests/test_utils.rb +76 -0
  43. data/lib/construqt/users.rb +19 -0
  44. data/lib/construqt/util.rb +163 -0
  45. data/lib/construqt/version.rb +3 -0
  46. data/lib/construqt/vlans.rb +51 -0
  47. data/lib/construqt.rb +92 -0
  48. metadata +105 -0
@@ -0,0 +1,65 @@
1
+
2
+ module Construqt
3
+ module Flavour
4
+ module Mikrotik
5
+ class Ipsec < OpenStruct
6
+ def initialize(cfg)
7
+ super(cfg)
8
+ end
9
+
10
+ def set_ip_ipsec_peer(cfg)
11
+ default = {
12
+ "address" => Schema.network.required.key,
13
+ "secret" => Schema.string.required,
14
+ "local-address" => Schema.required.address,
15
+ "passive" => Schema.boolean.default(false),
16
+ "port" => Schema.int.default(500),
17
+ "auth-method" => Schema.identifier.default("pre-shared-key"),
18
+ "generate-policy" => Schema.identifier.default("no"),
19
+ # "policy-group" => Schema.identifier.default("default"),
20
+ "exchange-mode" => Schema.identifier.default("main"),
21
+ "send-initial-contact" => Schema.boolean.default(true),
22
+ "nat-traversal" => Schema.boolean.default(true),
23
+ "proposal-check" => Schema.identifier.default("obey"),
24
+ "hash-algorithm" => Schema.identifier.default("sha1"),
25
+ "enc-algorithm" => Schema.identifier.default("aes-256"),
26
+ "dh-group" => Schema.identifier.default("modp1536"),
27
+ "lifetime" => Schema.interval.default("1d00:00:00"),
28
+ "lifebytes" => Schema.int.default(0),
29
+ "dpd-interval" => Schema.identifier.default("2m"),
30
+ "dpd-maximum-failures" => Schema.int.default(5)
31
+ }
32
+ self.host.result.render_mikrotik(default, cfg, "ip", "ipsec", "peer")
33
+ end
34
+
35
+ def set_ip_ipsec_policy(cfg)
36
+ default = {
37
+ "sa-src-address" => Schema.address.required.key,
38
+ "sa-dst-address" => Schema.address.required.key,
39
+ "src-address" => Schema.network.required,
40
+ "dst-address" => Schema.network.required,
41
+ "src-port" => Schema.port.default("any"),
42
+ "dst-port" => Schema.port.default("any"),
43
+ "protocol" => Schema.identifier.default("all"),
44
+ "action" => Schema.identifier.default("encrypt"),
45
+ "level" => Schema.identifier.default("require"),
46
+ "ipsec-protocols" => Schema.identifier.default("esp"),
47
+ "tunnel" => Schema.boolean.default(true),
48
+ "proposal" => Schema.identifier.default("s2b-proposal"),
49
+ "priority" => Schema.int.default(0)
50
+ }
51
+ #puts "#{cfg['sa-src-address'].class.name}=>#{cfg['sa-dst-address'].class.name} #{cfg['src-address'].class.name}=>#{cfg['dst-address'].class.name} #{cfg.keys}"
52
+ self.host.result.render_mikrotik(default, cfg, "ip", "ipsec", "policy")
53
+ end
54
+
55
+ def build_config(unused, unused2)
56
+ set_ip_ipsec_peer("address" => IPAddress.parse("#{self.other.remote.first_ipv6.to_s}/128"),
57
+ "local-address" => self.remote.first_ipv6,
58
+ "secret" => Util.password(self.cfg.password))
59
+ set_ip_ipsec_policy("src-address" => self.my.first_ipv6, "sa-src-address" => self.remote.first_ipv6,
60
+ "dst-address" => self.other.my.first_ipv6, "sa-dst-address" => self.other.remote.first_ipv6)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,182 @@
1
+ module Construqt
2
+ module Flavour
3
+ module Mikrotik
4
+ class Result
5
+ def initialize(host)
6
+ @remove_pre_condition = {}
7
+ @host = host
8
+ @result = {}
9
+ end
10
+
11
+ def host
12
+ @host
13
+ end
14
+
15
+ def empty?(name)
16
+ not @result[name]
17
+ end
18
+
19
+ def prepare(default, cfg, enable = true)
20
+ if enable
21
+ default['disabled'] = Schema.boolean.default(false)
22
+ end
23
+
24
+ result = {}
25
+ cfg.each do |key, val|
26
+ unless default[key]
27
+ Construqt.logger.debug("skip cfg unknown key:#{key} val:#{val}")
28
+ else
29
+ result[key] = val
30
+ end
31
+ end
32
+
33
+ keys = {}
34
+ default.each do |key, val|
35
+ if val.kind_of?(Schema)
36
+ val.field_name = key
37
+ throw "type must set of #{key}" unless val.type?
38
+ throw "required key:#{key} not set" if val.required? and (result[key].nil? or result[key].to_s.empty?)
39
+ result[key] = val.get_default if !val.get_default.nil? && result[key].nil?
40
+ keys[key] = result[key] if val.key?
41
+ else
42
+ throw "default type has to be a schema #{val}"
43
+ end
44
+ end
45
+
46
+ OpenStruct.new(
47
+ :key => keys.map{|k,v| "#{k}=#{default[k].serialize(v)}"}.sort.join(" && "),
48
+ :result => result,
49
+ :add_line => result.select{ |k,v|
50
+ if default[k].kind_of?(Schema) && default[k].noset?
51
+ false
52
+ else
53
+ !(v.to_s.empty?)
54
+ end
55
+
56
+ }.map{|k,v| "#{k}=#{default[k].serialize(v)}"}.sort.join(" ")
57
+ )
58
+ end
59
+
60
+ def render_mikrotik_set_direct(default, cfg, *path)
61
+ prepared = prepare(default, cfg, false)
62
+ add("set #{prepared.add_line}", nil, *path)
63
+ end
64
+
65
+ def render_mikrotik_set_by_key(default, cfg, *path)
66
+ prepared = prepare(default, cfg)
67
+ add("set [ find #{prepared.key} ] #{prepared.add_line}", nil, *path)
68
+ end
69
+
70
+ def render_mikrotik(default, cfg, *path)
71
+ enable = !cfg['no_auto_disable'] # HACK
72
+ cfg.delete("no_auto_disable")
73
+ prepared = prepare(default, cfg, enable)
74
+ ret = ["{"]
75
+ ret << " :local found [find "+prepared.key+"]"
76
+ ret << " :if ($found = \"\") do={"
77
+ ret << " :put "+"/#{path.join(' ')} add #{prepared.add_line}".inspect
78
+ ret << " add #{prepared.add_line}"
79
+ ret << " } else={"
80
+ #ret << " :put "+"/#{path.join(' ')} set #{prepared.add_line}".inspect
81
+ ret << " :local record [get $found]"
82
+ prepared.result.keys.sort.each do |key|
83
+ next if prepared.result[key].nil?
84
+ val = default[key].serialize(prepared.result[key])
85
+ next if val.to_s.empty?
86
+ compare_val = default[key].serialize_compare(prepared.result[key])
87
+ if compare_val
88
+ ret << " :if (($record->#{key.inspect})!=#{compare_val}) do={"
89
+ ret << " :put "+"/#{path.join(' ')} set [find #{prepared.key} ] #{key}=#{val}".inspect
90
+ ret << " set $found #{key}=#{val}"
91
+ ret << " }"
92
+ else
93
+ ret << " set $found #{key}=#{val}"
94
+ end
95
+ end
96
+
97
+ ret << " }"
98
+ ret << "}"
99
+ add(ret.join("\n"), prepared.key, *path)
100
+ end
101
+
102
+ def add(block, digest, *path)
103
+ key = File.join(*path)
104
+ @result[key] ||= []
105
+ @result[key] << OpenStruct.new(:digest => digest, :block => block, :path => path)
106
+ @result[key]
107
+ end
108
+
109
+ def add_remove_pre_condition(condition, *path)
110
+ @remove_pre_condition[path.join(' ')] = condition
111
+ end
112
+
113
+ def remove_condition(digests, key)
114
+ condition = @remove_pre_condition[key]
115
+ if condition
116
+ condition = "(#{condition})"
117
+ end
118
+
119
+ if digests.nil? || digests.compact.empty?
120
+ digest = nil
121
+ else
122
+ digest = "(!(#{digests.map{|i| "(#{i.digest})"}.join(" || ")}))"
123
+ end
124
+
125
+ term = [condition, digest].compact.join(" && ")
126
+ term.empty? ? "" : "remove [ find #{term} ]"
127
+ end
128
+
129
+ def commit
130
+ sorted = {}
131
+ @result.map do |path, blocks|
132
+ key = blocks.first.path.join(' ')
133
+ digests = blocks.select{|i| i.digest }
134
+
135
+ sorted[key] = Util.write_str([
136
+ "/#{key}",
137
+ blocks.map{|i|i.block}.join("\n"),
138
+ remove_condition(digests, key),
139
+ ""
140
+ ].join("\n"), File.join(@host.name, "#{path}.rsc"))
141
+ end
142
+
143
+ all=[
144
+ "system identity",
145
+ "system clock",
146
+ "system script",
147
+ "system scheduler",
148
+ "user",
149
+ "interface",
150
+ "interface bonding",
151
+ "interface bridge",
152
+ "interface bridge port",
153
+ "interface vlan",
154
+ "interface vrrp",
155
+ "interface gre6",
156
+ "ipv6 address",
157
+ "ipv6 route",
158
+ "ip address",
159
+ "ip dns",
160
+ "ip route",
161
+ "ip ipsec proposal",
162
+ "ip ipsec peer",
163
+ "ip ipsec policy",
164
+ "routing filter",
165
+ "routing bgp instance",
166
+ "routing bgp peer",
167
+ "tool graphing interface",
168
+ "ip service"
169
+ ].map do |path|
170
+ if sorted[path]
171
+ sorted[path]
172
+ else
173
+ Construqt.logger.warn "WARNING [#{path}] not found #{sorted.keys.join('-')}" unless sorted[path]
174
+ ""
175
+ end
176
+ end.join("\n")
177
+ Util.write_str(all, File.join(@host.name, "all.rsc"))
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,355 @@
1
+ module Construqt
2
+ module Flavour
3
+ module Mikrotik
4
+
5
+ class Schema
6
+ module Int
7
+ def self.serialize_compare(schema, val)
8
+ self.serialize(schema, val)
9
+ end
10
+
11
+ def self.serialize(schema, val)
12
+ return val if val.nil?
13
+ throw "only 0-9 are allowed [#{val}]" unless val.to_s.match(/^[0-9]+$/)
14
+ return val.to_i
15
+ end
16
+ end
17
+
18
+ module Boolean
19
+ def self.serialize_compare(schema, val)
20
+ throw "illegal type #{val.class.name}" unless val.kind_of?(TrueClass) || val.kind_of?(FalseClass)
21
+ val ? 'true' : 'false'
22
+ end
23
+
24
+ def self.serialize(schema, val)
25
+ throw "illegal type #{val.class.name}:#{schema.field_name}" unless val.kind_of?(TrueClass) || val.kind_of?(FalseClass)
26
+ val ? 'yes' : 'no'
27
+ end
28
+ end
29
+
30
+ module String
31
+ def self.serialize_compare(schema, val)
32
+ self.serialize(schema, val)
33
+ end
34
+
35
+ def self.serialize(schema, val)
36
+ return nil if val.nil? && schema.null?
37
+ return '""' if val.nil? || val.strip.empty?
38
+ return val.strip.to_s.inspect.gsub('$', '\\$')
39
+ end
40
+ end
41
+
42
+ module Source
43
+ def self.serialize_compare(schema, val)
44
+ nil
45
+ end
46
+
47
+ def self.serialize(schema, val)
48
+ return nil if val.nil? && schema.null?
49
+ return '""' if val.nil? || val.strip.empty?
50
+ return "{\n" + val.strip.to_s + "\n}\n"
51
+ end
52
+ end
53
+
54
+ module Interval
55
+ def self.serialize_compare(schema, val)
56
+ self.serialize(schema, val)
57
+ end
58
+
59
+ def self.serialize(schema, val)
60
+ throw "not in interval format hh:mm:ss" unless /^(\dd)*\d{1,2}:\d{2}:\d{2}$/.match(val)
61
+ return val
62
+ end
63
+ end
64
+
65
+ module Identifier
66
+ def self.serialize_compare(schema, val)
67
+ self.serialize(schema, val).inspect
68
+ end
69
+
70
+ def self.serialize(schema, val)
71
+ throw "only a-zA-Z0-9_- are allowed [#{val}]" unless val.match(/^[a-zA-Z0-9\-_]+$/)
72
+ return val.to_s
73
+ end
74
+ end
75
+
76
+ module Port
77
+ def self.serialize_compare(schema, val)
78
+ self.serialize(schema, val)
79
+ end
80
+
81
+ def self.serialize(schema, val)
82
+ val = '0' if val == 'any'
83
+ throw "only 0-9 are allowed [#{val}]" unless val.match(/^([Z0-9]+)$/)
84
+ return val.to_s
85
+ end
86
+ end
87
+
88
+ module Identifiers
89
+ def self.serialize_compare(schema, val)
90
+ self.serialize(schema, val, ';')
91
+ end
92
+
93
+ def self.serialize(schema, val, joiner=',')
94
+ '"'+val.split(',').map{|i| Identifier.serialize(schema, i) }.join(joiner).to_s+'"'
95
+ end
96
+ end
97
+
98
+ module Address
99
+ def self.serialize_compare(schema, val)
100
+ self.serialize(schema, val).inspect
101
+ end
102
+
103
+ def self.serialize(schema, val)
104
+ throw "Address:val must be ipaddress #{val.class.name} #{val} #{schema.field_name}" unless val.kind_of?(IPAddress::IPv6) || val.kind_of?(IPAddress::IPv4)
105
+ # throw "only 0-9:\.\/ are allowed #{val}" unless val.match(/^[a-fA-F0-9:\.\/]+$/)
106
+ return Flavour::Mikrotik.compress_address(val)
107
+ end
108
+ end
109
+
110
+ module AddrPrefix
111
+ def self.serialize_compare(schema, val)
112
+ self.serialize(schema, val).inspect
113
+ end
114
+
115
+ def self.serialize(schema, val)
116
+ throw "Address:val must be ipaddress #{val.class.name} #{val} #{schema.field_name}" unless val.kind_of?(IPAddress::IPv6) || val.kind_of?(IPAddress::IPv4)
117
+ # throw "only 0-9:\.\/ are allowed #{val}" unless val.match(/^[a-fA-F0-9:\.\/]+$/)
118
+ return "#{Flavour::Mikrotik.compress_address(val)}/#{val.prefix}"
119
+ end
120
+ end
121
+
122
+ module Network
123
+ def self.serialize_compare(schema, val)
124
+ self.serialize(schema, val.network).inspect
125
+ end
126
+
127
+ def self.serialize(schema, val)
128
+ throw "Network::val must be ipaddress #{val.class.name} #{val} #{schema.field_name}" unless val.kind_of?(IPAddress::IPv6) || val.kind_of?(IPAddress::IPv4)
129
+ #throw "only 0-9:\.\/ are allowed #{val}" unless val.match(/^[a-fA-F0-9:\.\/]+$/)
130
+ return "#{Flavour::Mikrotik.compress_address(val)}/#{val.prefix}"
131
+ end
132
+ end
133
+
134
+ module Addresses
135
+ def self.serialize_compare(schema, val)
136
+ self.serialize(schema, val)
137
+ end
138
+
139
+ def self.serialize(schema, val)
140
+ val.map{|i| Address.serialize(schema, i) }.join(',').to_s
141
+ end
142
+ end
143
+
144
+ def initialize
145
+ @required = false
146
+ @key = false
147
+ @noset = false
148
+ @type = nil
149
+ @default = nil
150
+ @null = false
151
+ @field_name = nil
152
+ end
153
+
154
+ def field_name=(a)
155
+ @field_name=a
156
+ end
157
+
158
+ def field_name
159
+ @field_name
160
+ end
161
+
162
+ def serialize_compare(val)
163
+ @type.serialize_compare(self, val)
164
+ end
165
+
166
+ def serialize(val)
167
+ @type.serialize(self, val)
168
+ end
169
+
170
+ def null?
171
+ @null
172
+ end
173
+
174
+ def type?
175
+ !@type.nil?
176
+ end
177
+
178
+ def null
179
+ @null = true
180
+ self
181
+ end
182
+
183
+ def required
184
+ @required = true
185
+ self
186
+ end
187
+
188
+ def required?
189
+ @required
190
+ end
191
+
192
+ def key
193
+ @key = true
194
+ self
195
+ end
196
+
197
+ def key?
198
+ @key
199
+ end
200
+
201
+ def noset
202
+ @noset = true
203
+ self
204
+ end
205
+
206
+ def noset?
207
+ @noset
208
+ end
209
+
210
+ def int
211
+ @type = Int
212
+ self
213
+ end
214
+
215
+ def boolean
216
+ @type = Boolean
217
+ self
218
+ end
219
+
220
+ def string
221
+ @type = String
222
+ self
223
+ end
224
+
225
+ def source
226
+ @type = Source
227
+ self
228
+ end
229
+
230
+ def interval
231
+ @type = Interval
232
+ self
233
+ end
234
+
235
+ def identifier
236
+ @type = Identifier
237
+ self
238
+ end
239
+
240
+ def port
241
+ @type = Port
242
+ self
243
+ end
244
+
245
+ def identifiers
246
+ @type = Identifiers
247
+ self
248
+ end
249
+
250
+ def source
251
+ @type = Source
252
+ self
253
+ end
254
+
255
+ def interval
256
+ @type = Interval
257
+ self
258
+ end
259
+
260
+ def addrprefix
261
+ @type = AddrPrefix
262
+ self
263
+ end
264
+
265
+ def address
266
+ @type = Address
267
+ self
268
+ end
269
+
270
+ def addresses
271
+ @type = Addresses
272
+ self
273
+ end
274
+
275
+ def network
276
+ @type = Network
277
+ self
278
+ end
279
+
280
+ def get_default
281
+ @default
282
+ end
283
+
284
+ def default(val)
285
+ @default = val
286
+ self
287
+ end
288
+
289
+ def self.default(val)
290
+ Schema.new.default(val)
291
+ end
292
+
293
+ def self.int
294
+ Schema.new.int
295
+ end
296
+
297
+ def self.boolean
298
+ Schema.new.boolean
299
+ end
300
+
301
+ def self.string
302
+ Schema.new.string
303
+ end
304
+
305
+ def self.interval
306
+ Schema.new.interval
307
+ end
308
+
309
+ def self.source
310
+ Schema.new.source
311
+ end
312
+
313
+ def self.port
314
+ Schema.new.port
315
+ end
316
+
317
+ def self.identifier
318
+ Schema.new.identifier
319
+ end
320
+
321
+ def self.identifiers
322
+ Schema.new.identifiers
323
+ end
324
+
325
+ def self.addresses
326
+ Schema.new.addresses
327
+ end
328
+
329
+ def self.addrprefix
330
+ Schema.new.addrprefix
331
+ end
332
+
333
+ def self.address
334
+ Schema.new.address
335
+ end
336
+
337
+ def self.network
338
+ Schema.new.network
339
+ end
340
+
341
+ def self.key
342
+ Schema.new.key
343
+ end
344
+
345
+ def self.noset
346
+ Schema.new.noset
347
+ end
348
+
349
+ def self.required
350
+ Schema.new.required
351
+ end
352
+ end
353
+ end
354
+ end
355
+ end