palo_alto 0.2.5 → 0.2.9
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.
- checksums.yaml +4 -4
- data/console.rb +0 -1
- data/examples/connecttest.rb +1 -1
- data/examples/test_config.rb +1 -1
- data/examples/test_log.rb +1 -1
- data/examples/test_op.rb +1 -1
- data/lib/palo_alto/config.rb +16477 -33486
- data/lib/palo_alto/version.rb +1 -1
- data/lib/palo_alto.rb +66 -49
- metadata +2 -2
data/lib/palo_alto/version.rb
CHANGED
data/lib/palo_alto.rb
CHANGED
@@ -74,30 +74,35 @@ module PaloAlto
|
|
74
74
|
|
75
75
|
module Helpers
|
76
76
|
class Rest
|
77
|
+
@http_clients = {} # will include [http_client, lock]
|
78
|
+
@global_lock = Mutex.new
|
79
|
+
|
77
80
|
def self.make_request(opts)
|
78
81
|
options = {}
|
79
|
-
options[:verify_ssl]
|
80
|
-
options[:timeout] = 60
|
82
|
+
options[:verify_ssl] ||= OpenSSL::SSL::VERIFY_PEER
|
81
83
|
|
82
|
-
headers
|
83
|
-
|
84
|
-
|
85
|
-
|
84
|
+
headers = {
|
85
|
+
'User-Agent': 'ruby-keystone-client',
|
86
|
+
'Accept': 'application/xml',
|
87
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
88
|
+
}
|
86
89
|
|
87
90
|
# merge in settings from method caller
|
88
91
|
options = options.merge(opts)
|
89
92
|
options[:headers].merge!(headers)
|
90
93
|
|
91
|
-
|
92
|
-
unless thread[:http]
|
93
|
-
thread[:http] = Net::HTTP.new(options[:host], options[:port])
|
94
|
-
thread[:http].use_ssl = true
|
95
|
-
thread[:http].verify_mode = options[:verify_ssl]
|
96
|
-
thread[:http].read_timeout = thread[:http].open_timeout = options[:timeout]
|
97
|
-
thread[:http].set_debug_output($stdout) if options[:debug].include?(:http)
|
98
|
-
end
|
94
|
+
http_client = lock = nil
|
99
95
|
|
100
|
-
|
96
|
+
@global_lock.synchronize do
|
97
|
+
unless (http_client, lock = @http_clients[options[:host]])
|
98
|
+
http_client = Net::HTTP.new(options[:host], 443)
|
99
|
+
http_client.use_ssl = true
|
100
|
+
http_client.verify_mode = options[:verify_ssl]
|
101
|
+
http_client.read_timeout = http_client.open_timeout = (options[:timeout] || 60)
|
102
|
+
http_client.set_debug_output(options[:debug].include?(:http) ? $stdout : nil)
|
103
|
+
@http_clients[options[:host]] = [http_client, (lock = Mutex.new)]
|
104
|
+
end
|
105
|
+
end
|
101
106
|
|
102
107
|
payload = options[:payload]
|
103
108
|
post_req = Net::HTTP::Post.new('/api/', options[:headers])
|
@@ -109,7 +114,11 @@ module PaloAlto
|
|
109
114
|
post_req.set_form_data(payload)
|
110
115
|
end
|
111
116
|
|
112
|
-
response =
|
117
|
+
response = lock.synchronize do
|
118
|
+
http_client.start unless http_client.started?
|
119
|
+
|
120
|
+
http_client.request(post_req)
|
121
|
+
end
|
113
122
|
|
114
123
|
case response.code
|
115
124
|
when '200'
|
@@ -159,7 +168,7 @@ module PaloAlto
|
|
159
168
|
end
|
160
169
|
|
161
170
|
class XML
|
162
|
-
attr_accessor :host, :
|
171
|
+
attr_accessor :host, :username, :password, :auth_key, :verify_ssl, :debug, :timeout
|
163
172
|
|
164
173
|
def execute(payload)
|
165
174
|
retried = false
|
@@ -167,10 +176,10 @@ module PaloAlto
|
|
167
176
|
# configure options for the request
|
168
177
|
options = {}
|
169
178
|
options[:host] = host
|
170
|
-
options[:port] = port
|
171
179
|
options[:verify_ssl] = verify_ssl
|
172
180
|
options[:payload] = payload
|
173
181
|
options[:debug] = debug
|
182
|
+
options[:timeout] = timeout || 180
|
174
183
|
options[:headers] = if payload[:type] == 'keygen'
|
175
184
|
{}
|
176
185
|
else
|
@@ -189,6 +198,7 @@ module PaloAlto
|
|
189
198
|
|
190
199
|
data = Nokogiri::XML.parse(text)
|
191
200
|
unless data.xpath('//response/@status').to_s == 'success'
|
201
|
+
warn 'command failed'
|
192
202
|
warn "sent:\n#{options.inspect}\n" if debug.include?(:sent_on_error)
|
193
203
|
warn "received:\n#{text.inspect}\n" if debug.include?(:received_on_error)
|
194
204
|
code = data.at_xpath('//response/@code')&.value.to_i # sometimes there is no code :( e.g. for 'op' errors
|
@@ -197,7 +207,6 @@ module PaloAlto
|
|
197
207
|
end
|
198
208
|
|
199
209
|
data
|
200
|
-
|
201
210
|
rescue TemporaryException => e
|
202
211
|
dont_retry_at = [
|
203
212
|
'Partial revert is not allowed. Full system commit must be completed.',
|
@@ -206,27 +215,25 @@ module PaloAlto
|
|
206
215
|
'Commit lock is not currently held by',
|
207
216
|
'You already own a config lock for scope '
|
208
217
|
]
|
209
|
-
if retried || dont_retry_at.any? { |x| e.message.start_with?(x) }
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
retry
|
216
|
-
end
|
218
|
+
raise e if retried || dont_retry_at.any? { |x| e.message.start_with?(x) }
|
219
|
+
|
220
|
+
warn "Got error #{e.inspect}; retrying" if debug.include?(:warnings)
|
221
|
+
retried = true
|
222
|
+
get_auth_key if e.is_a?(SessionTimedOutException)
|
223
|
+
retry
|
217
224
|
end
|
218
225
|
end
|
219
226
|
|
220
|
-
def commit!(all: false, device_groups: nil, wait_for_completion: true)
|
221
|
-
return nil if device_groups.is_a?(Array) && device_groups.empty?
|
227
|
+
def commit!(all: false, device_groups: nil, templates: nil, wait_for_completion: true, wait: 5, timeout: 480)
|
228
|
+
return nil if device_groups.is_a?(Array) && device_groups.empty? && templates.is_a?(Array) && templates.empty?
|
222
229
|
|
223
230
|
cmd = if all
|
224
231
|
'commit'
|
225
232
|
else
|
226
233
|
{ commit: { partial: [
|
227
234
|
{ 'admin': [username] },
|
228
|
-
device_groups ? { 'device-group': device_groups } : nil,
|
229
|
-
'no-template',
|
235
|
+
device_groups ? ( device_groups.empty? ? 'no-device-group' : { 'device-group': device_groups } ) : nil,
|
236
|
+
templates ? ( templates.empty? ? 'no-template' : { 'template': templates } ) : nil,
|
230
237
|
'no-template-stack',
|
231
238
|
'no-log-collector',
|
232
239
|
'no-log-collector-group',
|
@@ -236,12 +243,13 @@ module PaloAlto
|
|
236
243
|
{ 'shared-object': 'excluded' }
|
237
244
|
].compact } }
|
238
245
|
end
|
239
|
-
op.execute(cmd)
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
246
|
+
result = op.execute(cmd)
|
247
|
+
|
248
|
+
job_id = result.at_xpath('response/result/job')&.text
|
249
|
+
|
250
|
+
return result unless job_id && wait_for_completion
|
251
|
+
|
252
|
+
wait_for_job_completion(job_id, wait: wait, timeout: timeout) if job_id
|
245
253
|
end
|
246
254
|
|
247
255
|
def full_commit_required?
|
@@ -329,7 +337,7 @@ module PaloAlto
|
|
329
337
|
}
|
330
338
|
end
|
331
339
|
|
332
|
-
def wait_for_job_completion(job_id, wait: 5, timeout:
|
340
|
+
def wait_for_job_completion(job_id, wait: 5, timeout: 480)
|
333
341
|
cmd = { show: { jobs: { id: job_id } } }
|
334
342
|
start = Time.now
|
335
343
|
loop do
|
@@ -343,7 +351,8 @@ module PaloAlto
|
|
343
351
|
false
|
344
352
|
end
|
345
353
|
|
346
|
-
|
354
|
+
# wait: how long revert is retried (every 10 seconds)
|
355
|
+
def revert!(all: false, wait: 60)
|
347
356
|
cmd = if all
|
348
357
|
{ revert: 'config' }
|
349
358
|
else
|
@@ -359,16 +368,25 @@ module PaloAlto
|
|
359
368
|
{ 'shared-object': 'excluded' }
|
360
369
|
] } } }
|
361
370
|
end
|
362
|
-
|
371
|
+
|
372
|
+
waited = 0
|
373
|
+
begin
|
374
|
+
op.execute(cmd)
|
375
|
+
rescue StandardError => e
|
376
|
+
puts 'Revert failed; waiting and retrying'
|
377
|
+
sleep 10
|
378
|
+
waited += 1
|
379
|
+
retry while waited < wait
|
380
|
+
raise e
|
381
|
+
end
|
363
382
|
end
|
364
383
|
|
365
|
-
def initialize(host:,
|
366
|
-
self.host
|
367
|
-
self.
|
368
|
-
self.
|
369
|
-
self.
|
370
|
-
self.
|
371
|
-
self.debug = debug
|
384
|
+
def initialize(host:, username:, password:, verify_ssl: OpenSSL::SSL::VERIFY_NONE, debug: [])
|
385
|
+
self.host = host
|
386
|
+
self.username = username
|
387
|
+
self.password = password
|
388
|
+
self.verify_ssl = verify_ssl
|
389
|
+
self.debug = debug
|
372
390
|
|
373
391
|
@subclasses = {}
|
374
392
|
|
@@ -377,8 +395,7 @@ module PaloAlto
|
|
377
395
|
@arguments = [Expression.new(:this_node), []]
|
378
396
|
|
379
397
|
# attempt to obtain the auth_key
|
380
|
-
|
381
|
-
self.get_auth_key
|
398
|
+
get_auth_key
|
382
399
|
end
|
383
400
|
|
384
401
|
# Perform a query to the API endpoint for an auth_key based on the credentials provided
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: palo_alto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastian Roesner
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|