junos-ez-srx 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,239 @@
1
+ class Junos::Ez::SRX::PolicyRules::Provider < Junos::Ez::Provider::Parent
2
+
3
+ ### ---------------------------------------------------------------
4
+ ### XML top placement
5
+ ### ---------------------------------------------------------------
6
+
7
+ def xml_at_top
8
+ xml = @parent.xml_at_top
9
+ xml_element_top( xml, @name )
10
+ end
11
+
12
+ def xml_element_top( xml, name )
13
+ xml.policy {
14
+ xml.name name
15
+ return xml
16
+ }
17
+ end
18
+
19
+ ### ---------------------------------------------------------------
20
+ ### XML readers
21
+ ### ---------------------------------------------------------------
22
+
23
+ def xml_get_has_xml( xml )
24
+ xml.xpath('security/policies/policy/policy')[0]
25
+ end
26
+
27
+ def xml_read_parser( as_xml, as_hash )
28
+
29
+ set_has_status( as_xml, as_hash )
30
+
31
+ r_match = as_xml.xpath('match')
32
+ r_then = as_xml.xpath('then')
33
+
34
+ descr = as_xml.xpath('description').text
35
+ as_hash[:description] = descr unless descr.empty?
36
+
37
+ ## --------------------------------
38
+ ## "match" criteria
39
+ ## --------------------------------
40
+
41
+ as_hash[:match_srcs] = r_match.xpath('source-address').collect do |src|
42
+ src.text
43
+ end
44
+ as_hash[:match_dsts] = r_match.xpath('destination-address').collect do |dst|
45
+ dst.text
46
+ end
47
+ as_hash[:match_apps] = r_match.xpath('application').collect do |dst|
48
+ dst.text
49
+ end
50
+
51
+ ## --------------------------------
52
+ ## "then" criteria
53
+ ## --------------------------------
54
+
55
+ action = r_then.xpath('permit | reject | deny')[0]
56
+ as_hash[:action] = action.name.to_sym
57
+
58
+ xml_when_item( r_then.xpath('count' )){ as_hash[:count] = true }
59
+ xml_when_item( r_then.xpath('log/session-init')){ as_hash[:log_init] = true }
60
+ xml_when_item( r_then.xpath('log/session-close')){ as_hash[:log_close] = true }
61
+
62
+ return true
63
+ end
64
+
65
+ ### ---------------------------------------------------------------
66
+ ### XML property writers
67
+ ### ---------------------------------------------------------------
68
+
69
+ def xml_change_match_srcs( xml )
70
+ add, del = diff_property_array( :match_srcs )
71
+ return false if add.empty? and del.empty?
72
+
73
+ ele = :'source-address'
74
+ xml.match {
75
+ add.each{ |a| xml.send(ele, a) }
76
+ del.each{ |a| xml.send(ele, a, Netconf::JunosConfig::DELETE ) }
77
+ }
78
+ end
79
+
80
+ def xml_change_match_dsts( xml )
81
+ add, del = diff_property_array( :match_dsts )
82
+ return false if add.empty? and del.empty?
83
+
84
+ ele = :'destination-address'
85
+ xml.match {
86
+ add.each{ |a| xml.send(ele, a) }
87
+ del.each{ |a| xml.send(ele, a, Netconf::JunosConfig::DELETE ) }
88
+ }
89
+ end
90
+
91
+ def xml_change_match_apps( xml )
92
+ add, del = diff_property_array( :match_apps )
93
+ return false if add.empty? and del.empty?
94
+
95
+ xml.match {
96
+ add.each{ |a| xml.application a }
97
+ del.each{ |a| xml.application a, Netconf::JunosConfig::DELETE }
98
+ }
99
+ end
100
+
101
+ def xml_change_action( xml )
102
+ xml.then { xml.send( @should[:action] ) }
103
+ end
104
+
105
+ def xml_change_count( xml )
106
+ xml.then {
107
+ xml_set_or_delete_element( xml, 'count', @should[:count] )
108
+ }
109
+ end
110
+
111
+ def xml_change_log_init( xml )
112
+ xml.then { xml.log {
113
+ xml_set_or_delete_element( xml, 'session-init', @should[:log_init] )
114
+ }}
115
+ end
116
+
117
+ def xml_change_log_close( xml )
118
+ xml.then { xml.log {
119
+ xml_set_or_delete_element( xml, 'session-close', @should[:log_close] )
120
+ }}
121
+ end
122
+
123
+ end
124
+
125
+ ##### ---------------------------------------------------------------
126
+ ##### Provider collection methods
127
+ ##### ---------------------------------------------------------------
128
+
129
+ class Junos::Ez::SRX::PolicyRules::Provider
130
+
131
+ def build_list
132
+ xml_get = @parent.xml_at_top
133
+ xml_get.policy( :recurse => 'false' )
134
+ xml_got = @ndev.rpc.get_configuration( xml_get )
135
+ xml_got.xpath('//name').collect{|n| n.text }
136
+ end
137
+
138
+ def build_catalog
139
+ @catalog = {}
140
+ xml_got = @ndev.rpc.get_configuration( @parent.xml_at_top )
141
+ pols = xml_got.xpath('security/policies/policy')
142
+ pols.xpath('policy').each do |pol|
143
+ name = pol.xpath('name').text
144
+ @catalog[name] = {}
145
+ xml_read_parser( pol, @catalog[name] )
146
+ end
147
+ return @catalog
148
+ end
149
+
150
+ end
151
+
152
+ ##### ---------------------------------------------------------------
153
+ ##### Provider Misc. operational methods
154
+ ##### ---------------------------------------------------------------
155
+
156
+ class Junos::Ez::SRX::PolicyRules::Provider
157
+
158
+ ## 'catalog_expanded' does the equivalent of the show w/detail option
159
+ ## this expands the security object names into their exact values.
160
+ ## note that this processing could take some time given the size of
161
+ ## the address-books and application database involved. yo!
162
+
163
+ def catalog_expanded( policy_name = nil, opts = {} )
164
+
165
+ context = @parent.name
166
+
167
+ catalog_h = { :name => context }
168
+ catalog_h[:rules] = []
169
+
170
+ args = { :detail => true, :from_zone => context[0], :to_zone => context[1] }
171
+ args[:policy_name] = policy_name if policy_name
172
+ got = @ndev.rpc.get_firewall_policies( args )
173
+
174
+ got.xpath('security-context/policies/policy-information').each do |pi|
175
+ catalog_h[:rules] << _pi_to_h_( pi )
176
+ end
177
+
178
+ return catalog_h
179
+ end
180
+
181
+ ### ---------------------------------------------------------------
182
+ ### !!! PRIVATE METHODS
183
+ ### ---------------------------------------------------------------
184
+
185
+ private
186
+
187
+ def _pi_to_h_( xml )
188
+
189
+ name = xml.xpath('policy-name').text
190
+ action = xml.xpath('policy-action/action-type').text.to_sym
191
+
192
+ srcs = xml.xpath('source-addresses/source-address').collect do |i|
193
+ [ i.xpath('address-name').text, i.xpath('prefixes/address-prefix').text ]
194
+ end
195
+
196
+ dsts = xml.xpath('destination-addresses/destination-address').collect do |i|
197
+ [ i.xpath('address-name').text, i.xpath('prefixes/address-prefix').text ]
198
+ end
199
+
200
+ apps = {}
201
+ xml.xpath('applications/application').each do |i|
202
+ app_name = i.xpath('application-name').text
203
+ app_terms_xml = i.xpath('application-term')
204
+ app_terms_a = []
205
+ app_terms_xml.each do |app_term|
206
+ app_term_h = {}
207
+ app_term_h[:proto] = app_term.xpath('protocol').text
208
+ app_term_h[:timeout] = app_term.xpath('inactivity-timeout').text.to_i
209
+ if app_term_h[:proto] == 'icmp'
210
+ app_term_h[:icmp_type] = app_term.xpath('icmp-info/icmp-type').text
211
+ app_term_h[:icmp_code] = app_term.xpath('icmp-info/icmp-code').text
212
+ else
213
+ app_sports = [ app_term.xpath('source-port-range/low').text.to_i,
214
+ app_term.xpath('source-port-range/high').text.to_i ]
215
+ app_dports = [ app_term.xpath('destination-port-range/low').text.to_i,
216
+ app_term.xpath('destination-port-range/high').text.to_i ]
217
+ app_term_h[:src_ports] = app_sports
218
+ app_term_h[:dst_ports] = app_dports
219
+ end
220
+ app_terms_a << app_term_h
221
+ end
222
+ apps[app_name] = app_terms_a
223
+ end
224
+
225
+ to_h = {}
226
+ to_h[:name] = name
227
+ to_h[:action] = action
228
+ to_h[:match_srcs] = Hash[srcs]
229
+ to_h[:match_dsts] = Hash[dsts]
230
+ to_h[:match_apps] = apps
231
+
232
+ return to_h
233
+ end
234
+
235
+ end
236
+
237
+
238
+
239
+
@@ -0,0 +1,275 @@
1
+ class Junos::Ez::SRX::Zones::Provider < Junos::Ez::Provider::Parent
2
+
3
+ def initialize( p_obj, name = nil, opts = {} )
4
+ super
5
+
6
+ ## binding child providers ...
7
+ ## 'interfaces' for zone-interfaces
8
+ ## 'addrs' for address-book address entries
9
+ ## 'sets' for address-book address sets
10
+
11
+ Junos::Ez::SRX::Interfaces::Provider( self, :interfaces, :parent => self )
12
+ Junos::Ez::SRX::AddressBookEntries::Provider( self, :addrs, :parent => self )
13
+ Junos::Ez::SRX::AddressBookSets::Provider( self, :sets, :parent => self )
14
+ end
15
+
16
+ ### ---------------------------------------------------------------
17
+ ### XML top placement
18
+ ### ---------------------------------------------------------------
19
+
20
+ def xml_at_top
21
+ Nokogiri::XML::Builder.new{|x| x.configuration{
22
+ x.security { x.zones {
23
+ x.send(:'security-zone') {
24
+ x.name @name
25
+ return x
26
+ }
27
+ }}
28
+ }}
29
+ end
30
+
31
+ ## for this provider, we only want to retrieve the
32
+ ## configuration for the 'host-inbound-traffic' section
33
+
34
+ def xml_config_read!
35
+ xml = xml_at_top
36
+ xml.description
37
+ xml.send(:'host-inbound-traffic')
38
+ xml.interfaces
39
+ @ndev.rpc.get_configuration( xml )
40
+ end
41
+
42
+ ### ---------------------------------------------------------------
43
+ ### XML readers
44
+ ### ---------------------------------------------------------------
45
+
46
+ def xml_get_has_xml( xml )
47
+ zone_xml = xml.xpath('//security-zone')[0]
48
+ return zone_xml if zone_xml
49
+
50
+ # so there is a corner case if the zone exists, but doesn't
51
+ # have any interfaces or host-inbound-services. this is probably
52
+ # a highly unlikely case, since a zone needs at least one inteface
53
+ # to be useful. but just in case, let's check.
54
+ sh_zone = @ndev.rpc.get_zones_information(:get_zones_named_information => @name)
55
+ if sh_zone.xpath('zones-security')[0]
56
+ @has[:_exist] = true
57
+ @has[:_active] = true
58
+ @has[:host_inbound_services] = []
59
+ @has[:host_inbound_protocols] = []
60
+ @has[:interfaces] = []
61
+ end
62
+ nil
63
+ end
64
+
65
+ def xml_read_parser( as_xml, as_hash )
66
+ set_has_status( as_xml, as_hash )
67
+
68
+ xml_when_item( as_xml.xpath('description')){|item| as_hash[:description] = item.text }
69
+
70
+ host_ib = as_xml.xpath('host-inbound-traffic')
71
+ as_hash[:host_inbound_services] = host_ib.xpath('system-services').collect do |svc|
72
+ svc.xpath('name').text.strip
73
+ end
74
+ as_hash[:host_inbound_protocols] = host_ib.xpath('protocols').collect do |proto|
75
+ proto.xpath('name').text.strip
76
+ end
77
+
78
+ as_hash[:interfaces] = as_xml.xpath('interfaces/name').collect do |zif|
79
+ zif.text.strip
80
+ end
81
+
82
+ return true
83
+ end
84
+
85
+ ### ---------------------------------------------------------------
86
+ ### XML property writers
87
+ ### ---------------------------------------------------------------
88
+
89
+ def xml_change_host_inbound_services( xml )
90
+ add, del = diff_property_array( :host_inbound_services )
91
+ return false if add.empty? and del.empty?
92
+
93
+ xml.send( :'host-inbound-traffic' ) {
94
+ del.each do |i|
95
+ xml.send(:'system-services', Netconf::JunosConfig::DELETE) {
96
+ xml.name i
97
+ }
98
+ end
99
+ add.each{|i| xml.send(:'system-services', i ) }
100
+ }
101
+
102
+ end
103
+
104
+ def xml_change_host_inbound_protocols( xml )
105
+ add, del = diff_property_array( :host_inbound_protocols )
106
+ return false if add.empty? and del.empty?
107
+
108
+ xml.send( :'host-inbound-traffic' ) {
109
+ del.each do |i|
110
+ xml.protocols( Netconf::JunosConfig::DELETE ) {
111
+ xml.name i
112
+ }
113
+ end
114
+ add.each{ |i| xml.protocols i }
115
+ }
116
+ end
117
+
118
+ end
119
+
120
+ ##### ---------------------------------------------------------------
121
+ ##### Provider collection methods
122
+ ##### ---------------------------------------------------------------
123
+
124
+ class Junos::Ez::SRX::Zones::Provider
125
+
126
+ def build_list
127
+ zones = @ndev.rpc.get_zones_information
128
+ zones.xpath('zones-security/zones-security-zonename').collect do |zone|
129
+ zone.text.strip
130
+ end
131
+ end
132
+
133
+ def build_catalog
134
+ @catalog = {}
135
+
136
+ zlist = list!
137
+ xml_cfg = @ndev.rpc.get_configuration{|x|
138
+ x.security { x.zones {
139
+ zlist.each do |zone_name|
140
+ @catalog[zone_name] = {}
141
+ x.send(:'security-zone') {
142
+ x.name zone_name
143
+ x.description
144
+ x.send(:'host-inbound-traffic')
145
+ x.interfaces
146
+ }
147
+ end
148
+ }}
149
+ }
150
+
151
+ xml_cfg.xpath('//security-zone').each do |zone|
152
+ zn_name = zone.xpath('name').text.strip
153
+ @catalog[zn_name] = {}
154
+ xml_read_parser( zone, @catalog[zn_name] )
155
+ end
156
+
157
+ return @catalog
158
+ end
159
+
160
+ end
161
+
162
+ ##### ---------------------------------------------------------------
163
+ ##### Provider YAML/Hash methods
164
+ ##### ---------------------------------------------------------------
165
+
166
+ class Junos::Ez::SRX::Zones::Provider
167
+
168
+ ## ----------------------------------------------------------------
169
+ ## create an 'expanded' hash structure
170
+ ## ----------------------------------------------------------------
171
+
172
+ def to_h_expanded( opts = {} )
173
+ { :name => @name,
174
+ :_exist => @has[:_exist],
175
+ :_active => @has[:_active],
176
+ :host_inbound_services => @has[:host_inbound_services],
177
+ :host_inbound_protocols => @has[:host_inbound_protocols],
178
+ :interfaces => interfaces.catalog
179
+ }
180
+ end
181
+
182
+ def xml_from_h_expanded( from_hash, opts = {} )
183
+ raise ArgumentError, "This is not a provider" unless is_provider?
184
+ raise ArgumentError, ":name not provided in hash" unless from_hash[:name]
185
+
186
+ provd = self.class.new( @ndev, from_hash[:name], @opts )
187
+ provd.properties = Junos::Ez::Provider::PROPERTIES + Junos::Ez::SRX::Zones::PROPERTIES
188
+ provd[:host_inbound_services] = from_hash[:host_inbound_services] || []
189
+ provd[:host_inbound_protocols] = from_hash[:host_inbound_protocols] || []
190
+ provd[:_exist] = from_hash[:_exist] || true
191
+ provd[:_active] = from_hash[:_active] || true
192
+
193
+ # setup the XML for writing the complete configuration
194
+
195
+ xml_top = provd.xml_at_top
196
+ xml_add_here = xml_top.parent
197
+
198
+ Nokogiri::XML::Builder.with( xml_add_here ) do |xml|
199
+ provd.xml_build_change( xml )
200
+ end
201
+
202
+ # iterate through each of the policy rules. @@@ need
203
+ # to validate that the HASH actually contains this, yo!
204
+
205
+ from_hash[:interfaces].each do |name, hash|
206
+ Nokogiri::XML::Builder.with( xml_add_here ) do |xml|
207
+
208
+ # create the new object so we can generate XML on it
209
+ obj = Junos::Ez::SRX::Interfaces::Provider.new( @ndev, name, :parent => provd )
210
+
211
+ # generate the object specific XML inside
212
+ obj.should = hash || {}
213
+ obj_xml = obj.xml_element_top( xml, name )
214
+ obj.xml_build_change( obj_xml )
215
+ end
216
+ end
217
+
218
+ xml_top.parent[:replace] = "replace" if opts[:replace]
219
+ xml_top.doc.root
220
+ end
221
+
222
+ end
223
+
224
+
225
+ ##### ---------------------------------------------------------------
226
+ ##### Provider Misc. methods
227
+ ##### ---------------------------------------------------------------
228
+
229
+ class Junos::Ez::SRX::Zones::Provider
230
+
231
+ def find_route( ip_prefix = nil, opts = {} )
232
+ raise ArgumentError, "ip_prefix required" unless ip_prefix
233
+
234
+ ## do a standard route lookup to find the specific interface
235
+ ## providing a route for the provided ip_prefix
236
+
237
+ got = @ndev.rpc.get_route_information( :destination => ip_prefix, :best => true )
238
+ return nil unless rt = got.xpath('route-table/rt')[0]
239
+ rt_ent = rt.xpath('rt-entry')[0]
240
+
241
+ found = {}
242
+ found[:find] = ip_prefix
243
+ found[:found] = rt.xpath('rt-destination').text
244
+ found[:proto] = rt_ent.xpath('protocol-name').text
245
+ found[:pref] = rt_ent.xpath('preference').text.to_i
246
+ found[:via] = rt_ent.xpath('nh/via | nh/nh-local-interface').text
247
+
248
+ ## now find a zone based on the interface (via)
249
+
250
+ ifs = @ndev.rpc.get_interface_information( :interface_name => found[:via] )
251
+ found[:zone] = ifs.xpath('logical-interface/logical-interface-zone-name').text.strip
252
+
253
+ ## if the calling object is a resource, then see if the zone
254
+ ## matches on the lookup, and mark accordingly.
255
+
256
+ if @name; found[:zone_match] = (found[:zone] == @name) end
257
+
258
+ ## if opts[:addrs] is set to true, then search through the zone address book
259
+ ## to see what matches. first nab the zone provider depending if the calling
260
+ ## object is a provider or zone resource. If it's a zone resource then we
261
+ ## also need to make sure that the route lookup landed in this zone
262
+
263
+ if opts[:addrs]
264
+ if is_provider?
265
+ found[:addrs] = self[found[:zone]].addrs.find( ip_prefix )
266
+ else
267
+ found[:addrs] = (found[:zone_match] == true) ? self.addrs.find(ip_prefix) : nil
268
+ end
269
+ end
270
+
271
+ return found
272
+ end
273
+
274
+ end
275
+