junos-ez-srx 0.0.8

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.
@@ -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
+