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,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
+