palo_alto 0.5.0 → 0.5.1
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/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
|