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,55 @@
1
+ require 'yaml'
2
+ require 'net/netconf/jnpr'
3
+ require 'junos-ez/stdlib'
4
+ require 'junos-ez/srx'
5
+
6
+ login = {:target => 'vsrx', :username => 'jeremy', :password => 'jeremy1' }
7
+
8
+ ndev = Netconf::SSH.new( login )
9
+ ndev.open
10
+
11
+ $stdout.puts "Connected to #{login[:target]}"
12
+
13
+ Junos::Ez::Provider( ndev )
14
+ Junos::Ez::SRX::Zones.Provider( ndev, :zones )
15
+ Junos::Ez::SRX::Policies.Provider( ndev, :policies )
16
+
17
+ ### -----------------------------------------------------------------
18
+ ### Load all of the Zones YAML files
19
+ ### -----------------------------------------------------------------
20
+
21
+ Dir["*_ZONE_IFS.yaml"].each do |file|
22
+ $stdout.puts "Loading Zone Interface YAML contents into Junos: #{file} ..."
23
+ ndev.zones.create_from_yaml! :filename=>file
24
+ end
25
+
26
+ Dir["*_ZONE_ADDRS.yaml"].each do |file|
27
+ $stdout.puts "Loading Zone address YAML contents into Junos: #{file} ..."
28
+ ndev.zones.addrs.create_from_yaml! :filename=>file
29
+ end
30
+
31
+ Dir["*_ZONE_SETS.yaml"].each do |file|
32
+ $stdout.puts "Loading Zone address-set YAML contents into Junos: #{file} ..."
33
+ ndev.zones.sets.create_from_yaml! :filename=>file
34
+ end
35
+
36
+ ### -----------------------------------------------------------------
37
+ ### Load all of the Policy YAML files
38
+ ### -----------------------------------------------------------------
39
+
40
+ Dir['POLICY_*.yaml'].each do |file|
41
+ $stdout.puts "Loading security policy YAML contents into Junos: #{file} ... "
42
+ ndev.policies.create_from_yaml! :filename => file
43
+ end
44
+
45
+ $stdout.puts "Committing configuration ... "
46
+ ndev.rpc.commit_configuration
47
+
48
+ ndev.close
49
+
50
+
51
+
52
+
53
+
54
+
55
+
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+ require 'rake'
3
+ require 'net/netconf'
4
+
5
+ Gem::Specification.new do |s|
6
+
7
+ s.name = 'junos-ez-srx'
8
+ s.version = '0.0.8'
9
+ s.summary = "Junos NETCONF for SRX"
10
+ s.description = "Junos SRX gem for application development using NETCONF"
11
+ s.homepage = 'https://github.com/jeremyschulman/ruby-junos-ez-srx'
12
+ s.authors = ["Jeremy Schulman"]
13
+ s.email = 'jschulman@juniper.net'
14
+ s.files = FileList[ '*', 'lib/**/*.rb', 'examples/**/*.rb' ]
15
+
16
+ s.add_dependency('netconf')
17
+ s.add_dependency('ipaddress')
18
+ s.add_dependency('junos-ez-stdlib', '>= 0.1.0')
19
+
20
+ end
@@ -0,0 +1,150 @@
1
+ require "junos-ez/provider"
2
+
3
+ module Junos::Ez::SRX; end
4
+
5
+ module Junos::Ez::SRX::Zones
6
+
7
+ PROPERTIES = [
8
+ :description, ## description for Zone
9
+ :host_inbound_services, ## array of service names | nil
10
+ :host_inbound_protocols, ## array of protocol names | nil
11
+ :interfaces ## R/O array of interface names, will not catalog deeply
12
+ ]
13
+
14
+ def self.Provider( ndev, varsym, opts = {} )
15
+ newbie = Junos::Ez::SRX::Zones::Provider.new( ndev, nil, opts )
16
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
17
+ Junos::Ez::Provider.attach_instance_variable( ndev, varsym, newbie )
18
+ end
19
+
20
+ end
21
+
22
+ module Junos::Ez::SRX::Interfaces
23
+
24
+ PROPERTIES = [
25
+ :host_inbound_services,
26
+ :host_inbound_protocols,
27
+ ]
28
+
29
+ def self.Provider( on_obj, varsym, opts = {} )
30
+ newbie = Junos::Ez::SRX::Interfaces::Provider.new( on_obj, nil, opts )
31
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
32
+ Junos::Ez::Provider.attach_instance_variable( on_obj, varsym, newbie )
33
+ end
34
+
35
+ end
36
+
37
+ module Junos::Ez::SRX::AddressBookEntries
38
+
39
+ PROPERTIES = [
40
+ :description, # string
41
+ :ip_prefix, # address/pflen
42
+ ]
43
+
44
+ def self.Provider( on_obj, varsym, opts = {} )
45
+ newbie = Junos::Ez::SRX::AddressBookEntries::Provider.new( on_obj, nil, opts )
46
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
47
+ Junos::Ez::Provider.attach_instance_variable( on_obj, varsym, newbie )
48
+ end
49
+
50
+ end
51
+
52
+ module Junos::Ez::SRX::AddressBookSets
53
+
54
+ PROPERTIES = [
55
+ :description, # string
56
+ :addr_names, # array of address-names
57
+ :addr_sets, # array of address-sets, yo!
58
+ ]
59
+
60
+ def self.Provider( on_obj, varsym, opts = {} )
61
+ newbie = Junos::Ez::SRX::AddressBookSets::Provider.new( on_obj, nil, opts )
62
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
63
+ Junos::Ez::Provider.attach_instance_variable( on_obj, varsym, newbie )
64
+ end
65
+
66
+ end
67
+
68
+ module Junos::Ez::SRX::Policies
69
+
70
+ PROPERTIES = [
71
+ :rules_count, # Number of rules in this policy context
72
+ :rules # Provider to Junos::Ez::SRX::PolicyRules
73
+ ]
74
+
75
+ def self.Provider( on_obj, varsym, opts = {} )
76
+ newbie = Junos::Ez::SRX::Policies::Provider.new( on_obj, nil, opts )
77
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
78
+ Junos::Ez::Provider.attach_instance_variable( on_obj, varsym, newbie )
79
+ end
80
+
81
+ end
82
+
83
+ module Junos::Ez::SRX::PolicyRules
84
+
85
+ PROPERTIES = [
86
+ :description, # string description
87
+ :match_srcs, # array of sources
88
+ :match_dsts, # array of destinations
89
+ :match_apps, # array of apps
90
+ :action, # [ :permit, :reject, :deny ]
91
+ :count, # true | nil
92
+ :log_init, # true | nil
93
+ :log_close # true | nil
94
+ ]
95
+
96
+ def self.Provider( on_obj, varsym, opts = {} )
97
+ newbie = Junos::Ez::SRX::PolicyRules::Provider.new( on_obj, nil, opts )
98
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
99
+ Junos::Ez::Provider.attach_instance_variable( on_obj, varsym, newbie )
100
+ end
101
+
102
+ end
103
+
104
+ module Junos::Ez::SRX::Apps
105
+
106
+ PROPERTIES = [
107
+ :description, # string
108
+ :proto, # protocol, string | number
109
+ :timeout, # inactivity timeout, number
110
+ :icmp_type, # ICMP type, only for proto == 'icmp'
111
+ :icmp_code, # ICMP code, only for proto == 'icmp'
112
+ :dst_ports, # string-name | array [low, high]
113
+ :terms, # array of composite terms
114
+ ]
115
+
116
+ def self.Provider( on_obj, varsym, opts = {} )
117
+ newbie = Junos::Ez::SRX::Apps::Provider.new( on_obj, nil, opts )
118
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
119
+ Junos::Ez::Provider.attach_instance_variable( on_obj, varsym, newbie )
120
+ end
121
+
122
+ end
123
+
124
+ module Junos::Ez::SRX::AppSets
125
+
126
+ PROPERTIES = [
127
+ :description, # string
128
+ :app_names, # array of app-names
129
+ :app_sets, # array of app-sets, yes, sets can include other sets, yo!
130
+ ]
131
+
132
+ def self.Provider( on_obj, varsym, opts = {} )
133
+ newbie = Junos::Ez::SRX::AppSets::Provider.new( on_obj, nil, opts )
134
+ newbie.properties = Junos::Ez::Provider::PROPERTIES + PROPERTIES
135
+ Junos::Ez::Provider.attach_instance_variable( on_obj, varsym, newbie )
136
+ end
137
+
138
+ end
139
+
140
+ require 'junos-ez/srx/policies'
141
+ require 'junos-ez/srx/policyrules'
142
+ require 'junos-ez/srx/abooke'
143
+ require 'junos-ez/srx/abooks'
144
+ require 'junos-ez/srx/interfaces'
145
+ require 'junos-ez/srx/zones'
146
+ require 'junos-ez/srx/apps'
147
+ require 'junos-ez/srx/appsets'
148
+
149
+
150
+
@@ -0,0 +1,194 @@
1
+ ##### ---------------------------------------------------------------
2
+ ##### Provider resource methods
3
+ ##### ---------------------------------------------------------------
4
+
5
+ require 'ipaddress'
6
+
7
+ class Junos::Ez::SRX::AddressBookEntries::Provider < Junos::Ez::Provider::Parent
8
+
9
+ ### ---------------------------------------------------------------
10
+ ### XML top placement
11
+ ### ---------------------------------------------------------------
12
+
13
+ def xml_at_top
14
+ Nokogiri::XML::Builder.new{ |x| x.configuration{
15
+ x.security { x.zones {
16
+ x.send(:'security-zone') { x.name @parent.name
17
+ x.send(:'address-book') {
18
+ x.address { x.name @name
19
+ return x
20
+ }
21
+ }
22
+ }
23
+ }}
24
+ }}
25
+ end
26
+
27
+ def xml_element_top( xml, name )
28
+ xml.address { xml.name @name
29
+ return xml
30
+ }
31
+ end
32
+
33
+ ### ---------------------------------------------------------------
34
+ ### XML readers
35
+ ### ---------------------------------------------------------------
36
+
37
+ def xml_get_has_xml( xml )
38
+ xml.xpath('//address')[0]
39
+ end
40
+
41
+ def xml_read_parser( as_xml, as_hash )
42
+ set_has_status( as_xml, as_hash )
43
+ xml_when_item( as_xml.xpath('description')){|i| as_hash[:description] = i.text }
44
+ as_hash[:ip_prefix] = as_xml.xpath('ip-prefix').text
45
+ true
46
+ end
47
+
48
+ ### ---------------------------------------------------------------
49
+ ### XML writers
50
+ ### ---------------------------------------------------------------
51
+
52
+ def xml_change_ip_prefix( xml )
53
+ xml_set_or_delete( xml, 'ip-prefix', @should[:ip_prefix] )
54
+ end
55
+
56
+ end
57
+
58
+ ##### ---------------------------------------------------------------
59
+ ##### Provider collection methods
60
+ ##### ---------------------------------------------------------------
61
+
62
+ class Junos::Ez::SRX::AddressBookEntries::Provider
63
+
64
+ def build_list
65
+ @ndev.rpc.get_configuration{ |x|
66
+ x.security { x.zones {
67
+ x.send(:'security-zone') { x.name @parent.name
68
+ x.send(:'address-book') {
69
+ x.address({:recurse => 'false' })
70
+ }
71
+ }
72
+ }}
73
+ }.xpath('//address/name').collect{ |adr_name|
74
+ adr_name.text
75
+ }
76
+ end
77
+
78
+ def build_catalog
79
+ @catalog = {}
80
+
81
+ @ndev.rpc.get_configuration{ |x|
82
+ x.security { x.zones {
83
+ x.send(:'security-zone') { x.name @parent.name
84
+ x.send(:'address-book') {
85
+ x.address
86
+ }
87
+ }
88
+ }}
89
+ }.xpath('//address').each{ |adr|
90
+ name = adr.xpath('name').text
91
+ @catalog[name] = {}
92
+ xml_read_parser( adr, @catalog[name] )
93
+ }
94
+ @catalog
95
+ end
96
+
97
+ end
98
+
99
+ ##### ---------------------------------------------------------------
100
+ ##### Provider EXPANDED methods
101
+ ##### ---------------------------------------------------------------
102
+
103
+ class Junos::Ez::SRX::AddressBookEntries::Provider
104
+
105
+ ## -----------------------------------------------------
106
+ ## create a Hash from the existing provider information
107
+ ## -----------------------------------------------------
108
+
109
+ def to_h_expanded( opts = {} )
110
+ { :name => @parent.name, # zone name
111
+ :addrs => catalog
112
+ }
113
+ end
114
+
115
+ ## ----------------------------------------------------------------
116
+ ## create the XML for a complete policy rules set given a Hash
117
+ ## structure the mimics the provider and properties for the
118
+ ## Policy and associated PolicyRules
119
+ ## ----------------------------------------------------------------
120
+
121
+ def xml_from_h_expanded( from_hash, opts = {} )
122
+ zone_name = from_hash[:name]
123
+ raise ArgumentError, "zone-name as :name not provided in hash" unless zone_name
124
+
125
+ ## handle the case where 'self' is either a provider or a specific instance.
126
+
127
+ zone_pvd = self.is_provider? ? Junos::Ez::SRX::Zones::Provider.new( @ndev, zone_name ) : @parent
128
+ xml_top = zone_pvd.xml_at_top
129
+ xml_top.send(:'address-book')
130
+ xml_add_here = xml_top.parent.at('address-book')
131
+
132
+ ## now create objects and process the hash data accordingly
133
+
134
+ from_hash[:addrs].each do |name, hash|
135
+ Nokogiri::XML::Builder.with( xml_add_here ) do |xml|
136
+ # create the new object so we can generate XML on it
137
+ adr = self.class.new( @ndev, name, :parent => zone_pvd )
138
+ # generate the object specific XML inside
139
+ adr.should = hash
140
+ adr_xml = adr.xml_element_top( xml, name )
141
+ adr.xml_build_change( adr_xml )
142
+ end
143
+ end
144
+
145
+ xml_top.doc.root
146
+ end
147
+
148
+ end
149
+
150
+ ##### ---------------------------------------------------------------
151
+ ##### Provider operational methods
152
+ ##### ---------------------------------------------------------------
153
+
154
+ class Junos::Ez::SRX::AddressBookEntries::Provider
155
+
156
+ def find( addr )
157
+ lpm_cache_create!
158
+
159
+ # turn the given string into a searchable IPAddress object
160
+ find_addr = IPAddress( addr )
161
+
162
+ # search the cache for a matching item
163
+ found = @zab_lpm_cache.select{ |name, ab_addr, ipadr|
164
+ ipadr.include? find_addr
165
+ }
166
+
167
+ return nil if found.empty?
168
+
169
+ # return a sorted result with highest prefix first
170
+ found.sort_by{ |n,a,ip| ip.prefix }.reverse!
171
+ end
172
+
173
+ def lpm_find( addr )
174
+ return nil unless found = find( addr )
175
+ found[0]
176
+ end
177
+
178
+ private
179
+
180
+ def lpm_cache_create!
181
+ # cache is an array-of-arrays
182
+ # [0] = address-book name
183
+ # [1] = address-book address (string)
184
+ # [2] = IPAddress of [1] for searching
185
+ @zab_lpm_cache ||= catalog!.collect{ |name, hash|
186
+ adr = hash[:ip_prefix]
187
+ [ name, adr, IPAddress.parse( adr ) ]
188
+ }
189
+ end
190
+
191
+ def lpm_cache_clear!; @zab_lpm_cache = nil end
192
+
193
+ end
194
+
@@ -0,0 +1,164 @@
1
+ ##### ---------------------------------------------------------------
2
+ ##### Provider resource methods
3
+ ##### ---------------------------------------------------------------
4
+
5
+ class Junos::Ez::SRX::AddressBookSets::Provider < Junos::Ez::Provider::Parent
6
+
7
+ ### ---------------------------------------------------------------
8
+ ### XML top placement
9
+ ### ---------------------------------------------------------------
10
+
11
+ def xml_at_top
12
+ Nokogiri::XML::Builder.new{ |x| x.configuration{
13
+ x.security { x.zones {
14
+ x.send(:'security-zone') { x.name @parent.name
15
+ x.send(:'address-book') {
16
+ return xml_element_top( x, @name )
17
+ }
18
+ }
19
+ }}
20
+ }}
21
+ end
22
+
23
+ def xml_element_top( xml, name )
24
+ xml.send(:'address-set') {
25
+ xml.name name
26
+ return xml
27
+ }
28
+ end
29
+
30
+ ### ---------------------------------------------------------------
31
+ ### XML readers
32
+ ### ---------------------------------------------------------------
33
+
34
+ def xml_get_has_xml( xml )
35
+ xml.xpath('//address-set')[0]
36
+ end
37
+
38
+ def xml_read_parser( as_xml, as_hash )
39
+ set_has_status( as_xml, as_hash )
40
+
41
+ xml_when_item(as_xml.xpath('description')){|i| as_hash[:description] = i.text }
42
+ as_hash[:addr_names] = as_xml.xpath('address/name').collect{ |i| i.text }
43
+ as_hash[:addr_sets] = as_xml.xpath('address-set/name').collect{ |i| i.text }
44
+
45
+ true
46
+ end
47
+
48
+ ### ---------------------------------------------------------------
49
+ ### XML writers
50
+ ### ---------------------------------------------------------------
51
+
52
+ def xml_change_addr_names( xml )
53
+ add, del = diff_property_array( :addr_names )
54
+ return false if add.empty? and del.empty?
55
+
56
+ add.each{ |item| xml.address { xml.name item } }
57
+ del.each{ |item| xml.address( Netconf::JunosConfig::DELETE ) { xml.name item }}
58
+ end
59
+
60
+ def xml_change_addr_sets( xml )
61
+ add, del = diff_property_array( :addr_sets )
62
+ return false if add.empty? and del.empty?
63
+
64
+ add.each{ |item| xml.send(:'address-set') { xml.name item } }
65
+ del.each{ |item| xml.send(:'address-set', Netconf::JunosConfig::DELETE ) { xml.name item }}
66
+ end
67
+
68
+ end
69
+
70
+ ##### ---------------------------------------------------------------
71
+ ##### Provider collection methods
72
+ ##### ---------------------------------------------------------------
73
+
74
+ class Junos::Ez::SRX::AddressBookSets::Provider
75
+
76
+ def build_list
77
+ @ndev.rpc.get_configuration{ |x|
78
+ x.security { x.zones {
79
+ x.send(:'security-zone') { x.name @parent.name
80
+ x.send(:'address-book') {
81
+ x.send(:'address-set', {:recurse => 'false' })
82
+ }
83
+ }
84
+ }}
85
+ }.xpath('//address-set/name').collect{ |this|
86
+ this.text
87
+ }
88
+ end
89
+
90
+ def build_catalog
91
+
92
+ @catalog = {}
93
+
94
+ @ndev.rpc.get_configuration{ |x|
95
+ x.security { x.zones {
96
+ x.send(:'security-zone') { x.name @parent.name
97
+ x.send(:'address-book') {
98
+ x.send(:'address-set')
99
+ }
100
+ }
101
+ }}
102
+ }.xpath('//address-set').each{ |set|
103
+ name = set.xpath('name').text
104
+ @catalog[name] = {}
105
+ xml_read_parser( set, @catalog[name] )
106
+ }
107
+
108
+ return @catalog
109
+ end
110
+
111
+ end
112
+
113
+ ##### ---------------------------------------------------------------
114
+ ##### Provider EXPANDED methods
115
+ ##### ---------------------------------------------------------------
116
+
117
+ class Junos::Ez::SRX::AddressBookSets::Provider
118
+
119
+ ## -----------------------------------------------------
120
+ ## create a Hash from the existing provider information
121
+ ## -----------------------------------------------------
122
+
123
+ def to_h_expanded( opts = {} )
124
+ { :name => @parent.name, # zone name
125
+ :sets => catalog
126
+ }
127
+ end
128
+
129
+ ## ----------------------------------------------------------------
130
+ ## create the XML for a complete policy rules set given a Hash
131
+ ## structure the mimics the provider and properties for the
132
+ ## Policy and associated PolicyRules
133
+ ## ----------------------------------------------------------------
134
+
135
+ def xml_from_h_expanded( from_hash, opts = {} )
136
+ zone_name = from_hash[:name]
137
+ raise ArgumentError, ":name not provided in hash" unless from_hash[:name]
138
+
139
+ ## Need to set the Nokogiri xml_add_here (Element) to the address-book element
140
+ ## for provider zone (@parent)
141
+
142
+ zone_pvd = self.is_provider? ? Junos::Ez::SRX::Zones::Provider.new( @ndev, zone_name ) : @parent
143
+ xml_top = zone_pvd.xml_at_top
144
+ xml_top.send(:'address-book')
145
+ xml_add_here = xml_top.parent.at('address-book')
146
+
147
+ ## now create objects and process the hash data accordingly
148
+
149
+ from_hash[:sets].each do |name, hash|
150
+ Nokogiri::XML::Builder.with( xml_add_here ) do |xml|
151
+ # create the new object so we can generate XML on it
152
+ obj = self.class.new( @ndev, name, :parent => zone_pvd )
153
+ # generate the object specific XML inside
154
+ obj.should = hash
155
+ obj_xml = obj.xml_element_top( xml, name )
156
+ obj.xml_build_change( obj_xml )
157
+ end
158
+ end
159
+
160
+ xml_top.doc.root
161
+ end
162
+
163
+ end
164
+