palo_alto 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/examples/test_config.rb +31 -15
- data/examples/test_op.rb +52 -73
- data/lib/palo_alto/config.rb +137 -11
- data/lib/palo_alto/op.rb +59 -38
- data/lib/palo_alto/version.rb +1 -1
- data/lib/palo_alto.rb +41 -31
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35c89839bc38cd0398a88bd1c12c701b27e86de98bd1012a6c9d939898e9982a
|
4
|
+
data.tar.gz: 4c7e1ac46cf17e7d0780e768c2923dfa457e8cda93b8b3e714057e5909c3e764
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 351d244c00165c18d7d94d1c0e35d820db16f6cb586d613fe0d682df00fd1f49c68846548effa82d6568521fac0cfff31c62135bd8dfc81bb7b96f8ad3181d02
|
7
|
+
data.tar.gz: 65bb8bf61772a2630edb8354f9eb6098e25aaef0c420413bb00995f0eab9f6b4ab8c7a4d964a87ecd8921b9b53da9ad133ad249872e33badd59a0957a74db04e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
Version 0.5.1: Breaking changes for op commands, to be able to build more complex scenarios
|
2
|
+
Version 0.5.0: Update schema for Panorama 11.0
|
1
3
|
Version 0.4.1: Update schema for Panorama 10.2 for op commands
|
2
4
|
Version 0.4.0: Update schema for Panorama 10.2 for config
|
3
5
|
Version 0.3.0: Update schema for Panorama 10.1
|
data/examples/test_config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'palo_alto'
|
2
4
|
|
3
5
|
client = PaloAlto::XML.new(host: 'panorama-test', username: 'admin', password: 'Admin123!',
|
@@ -6,11 +8,11 @@ dg = 'PLAYGROUND'
|
|
6
8
|
|
7
9
|
# create a tag
|
8
10
|
tag_name = 'test'
|
9
|
-
|
10
11
|
new_tag = client.config.devices.entry(name: 'localhost.localdomain').device_group.entry(name: dg).tag.entry(name: tag_name).create!
|
11
12
|
new_tag.color = 'color23'
|
12
|
-
new_tag.
|
13
|
+
new_tag.set!
|
13
14
|
|
15
|
+
# get rules
|
14
16
|
# filtered rules:
|
15
17
|
# rules = client.config.devices.entry(name:'localhost.localdomain').device_group.entry(name: 'PLAYGROUND').pre_rulebase.security.rules
|
16
18
|
# .entry{ (child(:source).child(:member).text == "Net_10.1.1.0-24").or(child(:destination).child(:member).text == 'Net_10.1.1.0-24') }
|
@@ -19,46 +21,60 @@ new_tag.push!
|
|
19
21
|
# or:
|
20
22
|
#
|
21
23
|
# filter = (PaloAlto.child(:source).child(:member).text == "Net_10.1.1.0-24").or(PaloAlto.child(:destination).child(:member).text == 'Net_10.1.1.0-24')
|
22
|
-
# puts filter.to_xpath
|
24
|
+
# puts filter.to_xpath # prints generated Xpath filter
|
23
25
|
# => ./source/member/text()='Net_10.1.1.0-24'or./destination/member/text()='Net_10.1.1.0-24'
|
24
26
|
#
|
25
27
|
# rules = client.config.devices.entry(name:'localhost.localdomain').device_group.entry(name: 'PLAYGROUND').pre_rulebase.security.rules
|
26
28
|
# .entry{filter}.get_all
|
27
|
-
|
29
|
+
|
28
30
|
# also more advanced filters are possible:
|
29
|
-
# PaloAlto.not(PaloAlto.child(:'profile-setting').child(:group).child(:member) == 'IPS-Policy').and(
|
31
|
+
# filter = PaloAlto.not(PaloAlto.child(:'profile-setting').child(:group).child(:member) == 'IPS-Policy').and(
|
30
32
|
# PaloAlto.parenthesis(
|
31
33
|
# (PaloAlto.child(:tag).child(:member) == 'ips_enabled').or(
|
32
34
|
# PaloAlto.child(:tag).child(:member) == 'ips_force_enabled'
|
33
35
|
# )
|
34
36
|
# )
|
35
|
-
# )
|
36
|
-
#
|
37
|
+
# )
|
38
|
+
# puts filter.to_xpath
|
37
39
|
# => not(./profile-setting/group/member='IPS-Policy')and(./tag/member='ips_enabled'or./tag/member='ips_force_enabled')
|
38
40
|
|
39
41
|
rules = client.config.devices.entry(name: 'localhost.localdomain').device_group.entry(name: dg).pre_rulebase.security.rules.entry{}.get_all
|
40
42
|
|
41
|
-
rules.
|
43
|
+
rules.select! { |rule| rule.api_attributes['loc'] == dg } # filter rules inherited from upper device groups
|
42
44
|
|
43
45
|
pp rules
|
44
46
|
pp rules.length
|
45
47
|
|
46
|
-
pp rules.first.api_attributes # attributes like uuid and loc
|
47
|
-
pp rules.first.values # values as hash
|
48
|
-
|
49
48
|
rule = rules.first
|
49
|
+
|
50
|
+
pp rule.api_attributes # attributes like uuid and loc
|
51
|
+
pp rule.values # values as hash
|
52
|
+
|
50
53
|
rule.tag.member = [new_tag.name]
|
51
54
|
rule.group_tag = new_tag.name
|
52
55
|
rule.description += '....'
|
53
|
-
rule.
|
56
|
+
rule.edit!
|
54
57
|
|
58
|
+
# renaming rules
|
55
59
|
puts rule.to_xpath
|
56
60
|
rule.rename!('Test 1')
|
57
61
|
puts rule.to_xpath
|
58
|
-
|
62
|
+
puts rule.name
|
59
63
|
|
60
|
-
|
64
|
+
# Bulk changes on multiple rules:
|
65
|
+
rules = client.config.devices.entry(name: 'localhost.localdomain').device_group.entry(name: dg).pre_rulebase.security.rules.get
|
66
|
+
|
67
|
+
rules.entries.each do |name, rule|
|
68
|
+
next unless rule.values.dig('profile-setting', 'group', 'member') == ['Internal-detect']
|
69
|
+
|
70
|
+
rule.profile_setting.group.member = ['Internal']
|
71
|
+
# to remove profile-setting: rule.delete_child('profile-setting')
|
72
|
+
end
|
73
|
+
puts "Pushing all rules to #{rules.to_xpath}"
|
74
|
+
rules.edit!
|
61
75
|
|
62
76
|
# create a new template
|
63
77
|
new_template = client.config.devices.entry(name: 'localhost.localdomain').template.entry(name: 'testtemplate').create!
|
64
|
-
new_template.
|
78
|
+
new_template.set!
|
79
|
+
|
80
|
+
exit 0
|
data/examples/test_op.rb
CHANGED
@@ -1,31 +1,33 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
'
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
require 'palo_alto'
|
4
|
+
load '/usr/share/panorama-api/new_op.rb'
|
5
|
+
|
6
|
+
a = { commit: { partial:
|
7
|
+
{ admin: ['admin'],
|
8
|
+
'no-template': true,
|
9
|
+
'no-template-stack': true,
|
10
|
+
'no-log-collector': true,
|
11
|
+
'no-log-collector-group': true,
|
12
|
+
'no-wildfire-appliance': true,
|
13
|
+
'no-wildfire-appliance-cluster': true,
|
14
|
+
'device-and-network': 'excluded',
|
15
|
+
'shared-object': 'excluded' } } }
|
14
16
|
|
15
17
|
b = { show: { devices: 'all' } }
|
16
18
|
|
17
19
|
c = { revert: { config: {
|
18
|
-
partial:
|
19
|
-
|
20
|
-
'no-template',
|
21
|
-
'no-template-stack',
|
22
|
-
'no-log-collector',
|
23
|
-
'no-log-collector-group',
|
24
|
-
'no-wildfire-appliance',
|
25
|
-
'no-wildfire-appliance-cluster',
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
partial: {
|
21
|
+
admin: ['admin'],
|
22
|
+
'no-template': true,
|
23
|
+
'no-template-stack': true,
|
24
|
+
'no-log-collector': true,
|
25
|
+
'no-log-collector-group': true,
|
26
|
+
'no-wildfire-appliance': true,
|
27
|
+
'no-wildfire-appliance-cluster': true,
|
28
|
+
'device-and-network': 'excluded',
|
29
|
+
'shared-object': 'excluded'
|
30
|
+
}
|
29
31
|
} } }
|
30
32
|
|
31
33
|
d = { commit: nil }
|
@@ -44,18 +46,20 @@ k = { check: 'full-commit-required' }
|
|
44
46
|
|
45
47
|
l = { show: { config: { 'commit-scope': { partial: { admin: ['admin'] } } } } }
|
46
48
|
|
49
|
+
m = { show: { config: { 'commit-scope': { partial: { admin: %w[admin1 admin2] } } } } }
|
50
|
+
|
47
51
|
push_to_device = { 'commit-all': { 'shared-policy': { 'device-group': [{ name: 'TEST-DG' }] } } }
|
48
52
|
|
49
53
|
# validate:
|
50
54
|
p = { 'commit-all':
|
51
55
|
{
|
52
|
-
'shared-policy':
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
'shared-policy': {
|
57
|
+
'device-group': [{ name: 'PLAYGROUND' }],
|
58
|
+
'include-template': 'yes',
|
59
|
+
'merge-with-candidate-cfg': 'yes',
|
60
|
+
'force-template-values': 'no',
|
61
|
+
'validate-only': 'yes'
|
62
|
+
}
|
59
63
|
} }
|
60
64
|
|
61
65
|
i = { show: { query: { result: { id: 10_438 } } } }
|
@@ -63,64 +67,39 @@ i = { show: { query: { result: { id: 10_438 } } } }
|
|
63
67
|
# hit counts:
|
64
68
|
device_group = 'PLAYGROUND'
|
65
69
|
|
66
|
-
|
70
|
+
hc1 = {
|
67
71
|
show: {
|
68
|
-
'rule-hit-count':
|
72
|
+
'rule-hit-count': {
|
69
73
|
'device-group': [{
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
entry: [{
|
75
|
-
name: 'security'
|
76
|
-
}, {
|
77
|
-
rules: 'all'
|
78
|
-
}]
|
79
|
-
}]
|
74
|
+
name: device_group,
|
75
|
+
'pre-rulebase': [{
|
76
|
+
name: 'security',
|
77
|
+
rules: ['all']
|
80
78
|
}]
|
81
79
|
}]
|
82
|
-
}
|
80
|
+
}
|
83
81
|
}
|
84
82
|
}
|
85
83
|
|
86
84
|
# hit count for one rule, with more details:
|
87
85
|
rule_name = 'Rule 27'
|
88
|
-
|
86
|
+
hc2 = {
|
89
87
|
show: {
|
90
|
-
'rule-hit-count':
|
88
|
+
'rule-hit-count': {
|
91
89
|
'device-group': [{
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
'
|
96
|
-
entry: [{
|
97
|
-
name: 'security'
|
98
|
-
}, {
|
99
|
-
rules: {
|
100
|
-
'rule-name': [{
|
101
|
-
entry: [{
|
102
|
-
name: rule_name
|
103
|
-
}]
|
104
|
-
}]
|
105
|
-
}
|
106
|
-
}]
|
107
|
-
}]
|
90
|
+
name: device_group,
|
91
|
+
'pre-rulebase': [{
|
92
|
+
name: 'security',
|
93
|
+
rules: { 'rule-name': [{ name: rule_name }] }
|
108
94
|
}]
|
109
95
|
}]
|
110
|
-
}
|
96
|
+
}
|
111
97
|
}
|
112
98
|
}
|
113
99
|
|
114
100
|
client = PaloAlto::XML.new(host: 'panorama-test', username: 'admin', password: 'Admin123!', debug: %i[sent received])
|
115
101
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
puts '---------------------------'
|
121
|
-
pp client.op.execute(e)
|
122
|
-
puts '---------------------------'
|
123
|
-
|
124
|
-
# pp client.op.execute(f)
|
125
|
-
|
126
|
-
pp client.op.execute(k)
|
102
|
+
[a, b, c, d, e, f, g, h, j, k, l, m, push_to_device, p, i, hc1, hc2].each do |cmd|
|
103
|
+
puts client.op.to_xml(cmd)
|
104
|
+
puts '---------------------------'
|
105
|
+
end
|
data/lib/palo_alto/config.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# generated:
|
2
|
+
# generated: 2024-03-22 15:42:08 +0100
|
3
3
|
# rubocop:disable Style/FrozenStringLiteralComment
|
4
4
|
require 'openssl'
|
5
5
|
require 'nokogiri'
|
@@ -494,9 +494,8 @@ end
|
|
494
494
|
raise(ArgumentError, "Nothing matching found for #{value.inspect} (#{prop_hash.inspect})")
|
495
495
|
end
|
496
496
|
end
|
497
|
-
def xml_builder(xml, full_tree: false)
|
498
|
-
|
499
|
-
keys.map do |k|
|
497
|
+
def xml_builder(xml, full_tree: false, tag_filter: nil)
|
498
|
+
self._class.props.keys.select { |key| tag_filter.nil? || tag_filter.include?(key) }.map do |k|
|
500
499
|
next if k.start_with?('@')
|
501
500
|
v = prop_get(k, include_defaults: false)
|
502
501
|
next if v.nil?
|
@@ -508,6 +507,7 @@ end
|
|
508
507
|
end
|
509
508
|
if full_tree
|
510
509
|
@subclasses.each do |tag_name, subclass|
|
510
|
+
next if tag_filter && !tag_filter.include?(tag_name)
|
511
511
|
if subclass.is_a?(Hash)
|
512
512
|
subclass.each do |k2, subclass2|
|
513
513
|
tag_attr = k2.merge(subclass2.api_attributes.select { |attr, _| %w(uuid).include?(attr)})
|
@@ -625,14 +625,14 @@ my_prop = self._class.props[prop] or raise(InternalErrorException,
|
|
625
625
|
"Unknown attribute for #{self._class}: #{prop}")
|
626
626
|
@values[prop] = enforce_types(my_prop, value)
|
627
627
|
end
|
628
|
-
def to_xml(full_tree:, include_root:)
|
628
|
+
def to_xml(tag_filter: nil, full_tree:, include_root:)
|
629
629
|
builder = Nokogiri::XML::Builder.new do |xml|
|
630
630
|
xml.public_send(_section, begin
|
631
631
|
selector
|
632
632
|
rescue StandardError
|
633
633
|
nil
|
634
634
|
end) do
|
635
|
-
xml_builder(xml, full_tree: full_tree)
|
635
|
+
xml_builder(xml, full_tree: full_tree, tag_filter: tag_filter)
|
636
636
|
end
|
637
637
|
end
|
638
638
|
if include_root
|
@@ -652,12 +652,12 @@ element: xml_str
|
|
652
652
|
@client.execute(payload)
|
653
653
|
end
|
654
654
|
alias :push! :edit!
|
655
|
-
def set!
|
656
|
-
xml_str = to_xml(full_tree: true, include_root:
|
655
|
+
def set!(tag_filter: nil)
|
656
|
+
xml_str = to_xml(full_tree: true, include_root: false, tag_filter: tag_filter)
|
657
657
|
payload = {
|
658
658
|
type: 'config',
|
659
659
|
action: 'set',
|
660
|
-
xpath:
|
660
|
+
xpath: to_xpath,
|
661
661
|
element: xml_str
|
662
662
|
}
|
663
663
|
@client.execute(payload)
|
@@ -23659,6 +23659,66 @@ def has_multiple_values?; false; end
|
|
23659
23659
|
def _section
|
23660
23660
|
:entry
|
23661
23661
|
end
|
23662
|
+
class CustomWidget < XML::ConfigClass
|
23663
|
+
def has_multiple_values?; true; end
|
23664
|
+
def _section
|
23665
|
+
:'custom-widget'
|
23666
|
+
end
|
23667
|
+
class Entry < ArrayConfigClass
|
23668
|
+
def has_multiple_values?; false; end
|
23669
|
+
def _section
|
23670
|
+
:entry
|
23671
|
+
end
|
23672
|
+
@props = {'@name'=>{'node-type'=>'attr-req', 'type'=>'string', 'maxlen'=>'31', 'help-string'=>'positive number', 'regex'=>'[1-9][0-9]*'}, 'predefined-report'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}, 'custom-report'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}, 'pdf-summary-report'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}, 'log-view'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}, 'csv'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}}
|
23673
|
+
# positive number
|
23674
|
+
def name
|
23675
|
+
prop_get('@name')
|
23676
|
+
end
|
23677
|
+
def predefined_report
|
23678
|
+
prop_get('predefined-report')
|
23679
|
+
end
|
23680
|
+
def predefined_report=(val)
|
23681
|
+
prop_set('predefined-report', val)
|
23682
|
+
end
|
23683
|
+
def custom_report
|
23684
|
+
prop_get('custom-report')
|
23685
|
+
end
|
23686
|
+
def custom_report=(val)
|
23687
|
+
prop_set('custom-report', val)
|
23688
|
+
end
|
23689
|
+
def pdf_summary_report
|
23690
|
+
prop_get('pdf-summary-report')
|
23691
|
+
end
|
23692
|
+
def pdf_summary_report=(val)
|
23693
|
+
prop_set('pdf-summary-report', val)
|
23694
|
+
end
|
23695
|
+
def log_view
|
23696
|
+
prop_get('log-view')
|
23697
|
+
end
|
23698
|
+
def log_view=(val)
|
23699
|
+
prop_set('log-view', val)
|
23700
|
+
end
|
23701
|
+
def csv
|
23702
|
+
prop_get('csv')
|
23703
|
+
end
|
23704
|
+
def csv=(val)
|
23705
|
+
prop_set('csv', val)
|
23706
|
+
end
|
23707
|
+
end
|
23708
|
+
def selector_subclasses
|
23709
|
+
['entry']
|
23710
|
+
end
|
23711
|
+
def entries
|
23712
|
+
return @subclasses['entry']
|
23713
|
+
end
|
23714
|
+
def entry(*args, &block)
|
23715
|
+
array_class_setter(*args, klass: Entry, section: 'entry', &block)
|
23716
|
+
end
|
23717
|
+
@props = {}
|
23718
|
+
end
|
23719
|
+
def custom_widget
|
23720
|
+
maybe_register_subclass('custom-widget', CustomWidget.new(parent_instance: self, client: @client, create_children: @create_children))
|
23721
|
+
end
|
23662
23722
|
class All < XML::ConfigClass
|
23663
23723
|
def has_multiple_values?; true; end
|
23664
23724
|
def _section
|
@@ -23813,7 +23873,7 @@ end
|
|
23813
23873
|
def variable
|
23814
23874
|
maybe_register_subclass('variable', Variable.new(parent_instance: self, client: @client, create_children: @create_children))
|
23815
23875
|
end
|
23816
|
-
@props = {'@name'=>{'node-type'=>'attr-req', 'type'=>'string', 'maxlen'=>'63', 'subtype'=>'object-name', 'help-string'=>'alphanumeric string [ 0-9a-zA-Z._-]'}, 'title-page'=>{'node-type'=>'element', 'type'=>'bool', 'optional'=>'yes'}}
|
23876
|
+
@props = {'@name'=>{'node-type'=>'attr-req', 'type'=>'string', 'maxlen'=>'63', 'subtype'=>'object-name', 'help-string'=>'alphanumeric string [ 0-9a-zA-Z._-]'}, 'title-page'=>{'node-type'=>'element', 'type'=>'bool', 'optional'=>'yes'}, 'predefined'=>{'node-type'=>'element', 'type'=>'enum', 'enum'=>[{'value'=>'user-activity-report'}, {'value'=>'saas-application-usage-report'}]}}
|
23817
23877
|
# alphanumeric string [ 0-9a-zA-Z._-]
|
23818
23878
|
def name
|
23819
23879
|
prop_get('@name')
|
@@ -23824,6 +23884,12 @@ end
|
|
23824
23884
|
def title_page=(val)
|
23825
23885
|
prop_set('title-page', val)
|
23826
23886
|
end
|
23887
|
+
def predefined
|
23888
|
+
prop_get('predefined')
|
23889
|
+
end
|
23890
|
+
def predefined=(val)
|
23891
|
+
prop_set('predefined', val)
|
23892
|
+
end
|
23827
23893
|
end
|
23828
23894
|
def selector_subclasses
|
23829
23895
|
['entry']
|
@@ -75590,6 +75656,60 @@ def has_multiple_values?; false; end
|
|
75590
75656
|
def _section
|
75591
75657
|
:entry
|
75592
75658
|
end
|
75659
|
+
class CustomWidget < XML::ConfigClass
|
75660
|
+
def has_multiple_values?; true; end
|
75661
|
+
def _section
|
75662
|
+
:'custom-widget'
|
75663
|
+
end
|
75664
|
+
class Entry < ArrayConfigClass
|
75665
|
+
def has_multiple_values?; false; end
|
75666
|
+
def _section
|
75667
|
+
:entry
|
75668
|
+
end
|
75669
|
+
@props = {'@name'=>{'node-type'=>'attr-req', 'type'=>'string', 'maxlen'=>'31', 'help-string'=>'positive number', 'regex'=>'[1-9][0-9]*'}, 'custom-report'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}, 'pdf-summary-report'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}, 'log-view'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}, 'csv'=>{'node-type'=>'element', 'type'=>'string', 'maxlen'=>'63'}}
|
75670
|
+
# positive number
|
75671
|
+
def name
|
75672
|
+
prop_get('@name')
|
75673
|
+
end
|
75674
|
+
def custom_report
|
75675
|
+
prop_get('custom-report')
|
75676
|
+
end
|
75677
|
+
def custom_report=(val)
|
75678
|
+
prop_set('custom-report', val)
|
75679
|
+
end
|
75680
|
+
def pdf_summary_report
|
75681
|
+
prop_get('pdf-summary-report')
|
75682
|
+
end
|
75683
|
+
def pdf_summary_report=(val)
|
75684
|
+
prop_set('pdf-summary-report', val)
|
75685
|
+
end
|
75686
|
+
def log_view
|
75687
|
+
prop_get('log-view')
|
75688
|
+
end
|
75689
|
+
def log_view=(val)
|
75690
|
+
prop_set('log-view', val)
|
75691
|
+
end
|
75692
|
+
def csv
|
75693
|
+
prop_get('csv')
|
75694
|
+
end
|
75695
|
+
def csv=(val)
|
75696
|
+
prop_set('csv', val)
|
75697
|
+
end
|
75698
|
+
end
|
75699
|
+
def selector_subclasses
|
75700
|
+
['entry']
|
75701
|
+
end
|
75702
|
+
def entries
|
75703
|
+
return @subclasses['entry']
|
75704
|
+
end
|
75705
|
+
def entry(*args, &block)
|
75706
|
+
array_class_setter(*args, klass: Entry, section: 'entry', &block)
|
75707
|
+
end
|
75708
|
+
@props = {}
|
75709
|
+
end
|
75710
|
+
def custom_widget
|
75711
|
+
maybe_register_subclass('custom-widget', CustomWidget.new(parent_instance: self, client: @client, create_children: @create_children))
|
75712
|
+
end
|
75593
75713
|
class All < XML::ConfigClass
|
75594
75714
|
def has_multiple_values?; true; end
|
75595
75715
|
def _section
|
@@ -75744,7 +75864,7 @@ end
|
|
75744
75864
|
def variable
|
75745
75865
|
maybe_register_subclass('variable', Variable.new(parent_instance: self, client: @client, create_children: @create_children))
|
75746
75866
|
end
|
75747
|
-
@props = {'@name'=>{'node-type'=>'attr-req', 'type'=>'string', 'maxlen'=>'63', 'subtype'=>'object-name', 'help-string'=>'alphanumeric string [ 0-9a-zA-Z._-]'}, 'title-page'=>{'node-type'=>'element', 'type'=>'bool', 'optional'=>'yes'}}
|
75867
|
+
@props = {'@name'=>{'node-type'=>'attr-req', 'type'=>'string', 'maxlen'=>'63', 'subtype'=>'object-name', 'help-string'=>'alphanumeric string [ 0-9a-zA-Z._-]'}, 'title-page'=>{'node-type'=>'element', 'type'=>'bool', 'optional'=>'yes'}, 'predefined'=>{'node-type'=>'element', 'type'=>'enum', 'enum'=>[{'value'=>'user-activity-report'}, {'value'=>'saas-application-usage-report'}]}}
|
75748
75868
|
# alphanumeric string [ 0-9a-zA-Z._-]
|
75749
75869
|
def name
|
75750
75870
|
prop_get('@name')
|
@@ -75755,6 +75875,12 @@ end
|
|
75755
75875
|
def title_page=(val)
|
75756
75876
|
prop_set('title-page', val)
|
75757
75877
|
end
|
75878
|
+
def predefined
|
75879
|
+
prop_get('predefined')
|
75880
|
+
end
|
75881
|
+
def predefined=(val)
|
75882
|
+
prop_set('predefined', val)
|
75883
|
+
end
|
75758
75884
|
end
|
75759
75885
|
def selector_subclasses
|
75760
75886
|
['entry']
|
data/lib/palo_alto/op.rb
CHANGED
@@ -75,63 +75,84 @@ module PaloAlto
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
79
|
-
|
78
|
+
def xml_builder_iter(xml, ops, data)
|
79
|
+
raise 'No Ops?!' if ops.nil?
|
80
|
+
|
81
|
+
case data
|
80
82
|
when String
|
81
|
-
section =
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
data
|
83
|
+
section = data
|
84
|
+
data2 = nil
|
85
|
+
xml_builder(xml, ops, section, data2)
|
86
|
+
when Hash, Array
|
87
|
+
data.each do |section, data2|
|
88
|
+
xml_builder(xml, ops, section, data2)
|
89
|
+
end
|
86
90
|
else
|
87
|
-
raise
|
88
|
-
end
|
89
|
-
|
90
|
-
unless ops.key?(section.to_s)
|
91
|
-
err = "Error #{section} does not exist. Valid: " + ops.keys.pretty_inspect
|
92
|
-
raise err
|
91
|
+
raise data.pretty_inspect
|
93
92
|
end
|
93
|
+
end
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
section
|
95
|
+
def xml_builder(xml, ops, section, data, type = ops[section.to_s]&.[](:obj))
|
96
|
+
ops_tree = ops[section.to_s] || raise("no ops tree for section #{section}, #{ops.keys.inspect}")
|
97
|
+
# pp [:xml_builder, :section, section, :type, type]
|
98
|
+
# obj = data
|
98
99
|
|
99
|
-
case
|
100
|
+
case type
|
100
101
|
when :element
|
101
|
-
xml.public_send(section, data)
|
102
|
+
xml.public_send(escape_xpath_tag(section), data)
|
102
103
|
when :array
|
103
|
-
xml.public_send(section) do
|
104
|
+
xml.public_send(escape_xpath_tag(section)) do
|
105
|
+
raise 'data is Hash and should be Array' if data.is_a?(Hash)
|
106
|
+
|
104
107
|
data.each do |el|
|
105
108
|
key = ops_tree.keys.first
|
106
|
-
|
109
|
+
case el
|
110
|
+
when Hash
|
111
|
+
attr = ops_tree[key].find { |_k, v| v.is_a?(Hash) && v[:obj] == :'attr-req' }.first
|
112
|
+
xml.public_send(escape_xpath_tag(key), { attr => el[attr.to_sym] }) do
|
113
|
+
remaining_attrs = el.reject { |k, _v| k == attr.to_sym }
|
114
|
+
|
115
|
+
if remaining_attrs.any?
|
116
|
+
xml_builder(xml, ops_tree[key], remaining_attrs.keys.first.to_s, remaining_attrs.values.first,
|
117
|
+
:array)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
when String
|
121
|
+
xml.public_send(key, el)
|
122
|
+
end
|
107
123
|
end
|
108
124
|
end
|
109
125
|
when :sequence
|
110
|
-
if data.nil?
|
111
|
-
xml.send(section)
|
126
|
+
if data.nil? || data == true
|
127
|
+
xml.send(escape_xpath_tag(section))
|
112
128
|
elsif data.is_a?(Hash)
|
113
|
-
xml.send(section)
|
114
|
-
|
129
|
+
xml.send(escape_xpath_tag(section)) do
|
130
|
+
xml_builder_iter(xml, ops_tree, data)
|
115
131
|
end
|
116
|
-
else # array
|
132
|
+
else # array, what else could it be?!
|
133
|
+
raise "Unknown: #{attr.inspect}" unless data.is_a?(Array)
|
117
134
|
|
118
|
-
if data.
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
135
|
+
raise 'Too many hashes in an array, please update' if data.length > 1
|
136
|
+
|
137
|
+
key = ops_tree.keys.first
|
138
|
+
attr_name = ops_tree[key].find { |_k, v| v.is_a?(Hash) && v[:obj] == :'attr-req' }.first
|
139
|
+
|
140
|
+
hash = data.first.dup
|
141
|
+
|
142
|
+
data = [hash.reject { |k| k == attr_name.to_sym }]
|
143
|
+
attr = { attr_name => hash[attr_name.to_sym] }
|
124
144
|
|
125
|
-
xml.public_send(section
|
126
|
-
|
127
|
-
|
145
|
+
xml.public_send(escape_xpath_tag(section)) do
|
146
|
+
xml.public_send(escape_xpath_tag(key), attr) do
|
147
|
+
data.each do |child|
|
148
|
+
xml_builder_iter(xml, ops_tree[key], child)
|
149
|
+
end
|
128
150
|
end
|
129
151
|
end
|
130
152
|
end
|
131
153
|
when :union
|
132
|
-
|
133
|
-
|
134
|
-
xml_builder(xml, ops_tree, v)
|
154
|
+
xml.public_send(escape_xpath_tag(section)) do
|
155
|
+
xml_builder_iter(xml, ops[section.to_s], data)
|
135
156
|
end
|
136
157
|
else
|
137
158
|
raise ops_tree[:obj].pretty_inspect
|
@@ -141,7 +162,7 @@ module PaloAlto
|
|
141
162
|
|
142
163
|
def to_xml(obj)
|
143
164
|
builder = Nokogiri::XML::Builder.new do |xml|
|
144
|
-
|
165
|
+
xml_builder_iter(xml, @@ops, obj)
|
145
166
|
end
|
146
167
|
builder.doc.root.to_xml
|
147
168
|
end
|
data/lib/palo_alto/version.rb
CHANGED
data/lib/palo_alto.rb
CHANGED
@@ -129,6 +129,7 @@ module PaloAlto
|
|
129
129
|
raise SessionTimedOutException
|
130
130
|
when '400', '403'
|
131
131
|
begin
|
132
|
+
pp [:error, options[:host], response.code, response.message]
|
132
133
|
data = Nokogiri::XML.parse(response.body)
|
133
134
|
message = data.xpath('//response/response/msg').text
|
134
135
|
code = response.code.to_i
|
@@ -194,7 +195,7 @@ module PaloAlto
|
|
194
195
|
new_xpath = 'response/result/' + search_xpath[(remove+2)..]
|
195
196
|
|
196
197
|
results = cache.xpath(new_xpath)
|
197
|
-
|
198
|
+
xml = Nokogiri.parse("<?xml version=\"1.0\"?><response><result>#{results.to_s}</result></response>")
|
198
199
|
|
199
200
|
if debug.include?(:statistics)
|
200
201
|
warn "Elapsed for parsing cache: #{Time.now - start_time} seconds"
|
@@ -215,7 +216,7 @@ module PaloAlto
|
|
215
216
|
options[:verify_ssl] = verify_ssl
|
216
217
|
options[:payload] = payload
|
217
218
|
options[:debug] = debug
|
218
|
-
options[:timeout] = timeout ||
|
219
|
+
options[:timeout] = timeout || 600
|
219
220
|
options[:headers] = if payload[:type] == 'keygen'
|
220
221
|
{}
|
221
222
|
else
|
@@ -262,6 +263,7 @@ module PaloAlto
|
|
262
263
|
rescue TemporaryException => e
|
263
264
|
dont_retry_at = [
|
264
265
|
'Partial revert is not allowed. Full system commit must be completed.',
|
266
|
+
'Local commit jobs are queued. Revert operation is not allowed.',
|
265
267
|
'Config for scope ',
|
266
268
|
'Config is not currently locked for scope ',
|
267
269
|
'Commit lock is not currently held by',
|
@@ -275,7 +277,7 @@ module PaloAlto
|
|
275
277
|
max_retries = if dont_retry_at.any? { |str| e.message.start_with?(str) }
|
276
278
|
0
|
277
279
|
elsif e.message.start_with?('Timed out while getting config lock. Please try again.')
|
278
|
-
|
280
|
+
30
|
279
281
|
else
|
280
282
|
1
|
281
283
|
end
|
@@ -321,23 +323,31 @@ module PaloAlto
|
|
321
323
|
cmd = if all
|
322
324
|
'commit'
|
323
325
|
else
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
'no-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
326
|
+
commit_partial = {
|
327
|
+
'no-template-stack': true,
|
328
|
+
'no-log-collector': true,
|
329
|
+
'no-log-collector-group': true,
|
330
|
+
'no-wildfire-appliance': true,
|
331
|
+
'no-wildfire-appliance-cluster': true,
|
332
|
+
'device-and-network': 'excluded',
|
333
|
+
'shared-object': 'excluded'
|
334
|
+
}
|
335
|
+
|
336
|
+
if device_groups
|
337
|
+
commit_partial.merge!(device_groups.empty? ? {'no-device-group': true} : { 'device-group': device_groups })
|
338
|
+
end
|
339
|
+
|
340
|
+
if templates
|
341
|
+
commit_partial.merge!(templates.empty? ? {'no-template': true} : { 'template': templates })
|
342
|
+
end
|
343
|
+
|
344
|
+
if admins
|
345
|
+
commit_partial.merge!({'admin': admins})
|
346
|
+
end
|
347
|
+
|
348
|
+
{ commit: { partial: commit_partial } }
|
340
349
|
end
|
350
|
+
|
341
351
|
result = op.execute(cmd)
|
342
352
|
|
343
353
|
return result if raw_result
|
@@ -358,7 +368,7 @@ module PaloAlto
|
|
358
368
|
def primary_active?
|
359
369
|
cmd = { show: { 'high-availability': 'state' } }
|
360
370
|
state = op.execute(cmd)
|
361
|
-
state.at_xpath('response/result/local-info/state')
|
371
|
+
state.at_xpath('response/result/local-info/state')&.text == 'primary-active'
|
362
372
|
end
|
363
373
|
|
364
374
|
# area: config, commit
|
@@ -500,17 +510,17 @@ module PaloAlto
|
|
500
510
|
cmd = if all
|
501
511
|
{ revert: 'config' }
|
502
512
|
else
|
503
|
-
{ revert: { config: { partial:
|
504
|
-
|
505
|
-
'no-template',
|
506
|
-
'no-template-stack',
|
507
|
-
'no-log-collector',
|
508
|
-
'no-log-collector-group',
|
509
|
-
'no-wildfire-appliance',
|
510
|
-
'no-wildfire-appliance-cluster',
|
511
|
-
|
512
|
-
|
513
|
-
|
513
|
+
{ revert: { config: { partial: {
|
514
|
+
'admin': [username],
|
515
|
+
'no-template': true,
|
516
|
+
'no-template-stack': true,
|
517
|
+
'no-log-collector': true,
|
518
|
+
'no-log-collector-group': true,
|
519
|
+
'no-wildfire-appliance': true,
|
520
|
+
'no-wildfire-appliance-cluster': true,
|
521
|
+
'device-and-network': 'excluded',
|
522
|
+
'shared-object': 'excluded'
|
523
|
+
} } } }
|
514
524
|
end
|
515
525
|
|
516
526
|
waited = 0
|
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.5.
|
4
|
+
version: 0.5.1
|
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: 2024-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|