ruby-jss 2.1.0b4 → 2.1.0
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/CHANGES.md +9 -6
- data/bin/cgrouper +142 -162
- data/bin/jamfHelperBackgrounder +4 -2
- data/bin/netseg-update +9 -5
- data/lib/jamf/api/classic/api_objects/computer.rb +1 -1
- data/lib/jamf/api/classic/api_objects/mobile_device_application.rb +1 -1
- data/lib/jamf/api/classic/api_objects/patch_title.rb +4 -4
- data/lib/jamf/api/classic/xml_workaround.rb +3 -1
- data/lib/jamf/api/connection/attributes.rb +8 -8
- data/lib/jamf/api/connection/classic_api.rb +10 -1
- data/lib/jamf/api/connection/constants.rb +2 -0
- data/lib/jamf/api/connection/jamf_pro_api.rb +7 -1
- data/lib/jamf/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 970c4289986bb3f0b3ea9a60b31777a29b4c927879a3204d28c3f9bdd46a2a9f
|
4
|
+
data.tar.gz: f75ae4ae8ba5bd0cfadb065c62f495fcb4eea86b2473aa5d8357569e9ce49059
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b86acc435cc02cdd0976361305331b4bf98b176fd25c8accb791cfba794c7bdf6d42d94d62cc76b11cb510e9c3ac23495ac99aa244e76a39e5e6e061aeeae4a8
|
7
|
+
data.tar.gz: 31f95548e2cb64bedb1781977222c705183c3e866ce8c8a9fb5532dfdbdeabe11d59faa92818c8506d5235d2fc868d1eb58d949b17ecc5f6c3d66bafde910750
|
data/CHANGES.md
CHANGED
@@ -14,25 +14,28 @@ __Please update all installations of ruby-jss to at least v1.6.0.__
|
|
14
14
|
|
15
15
|
Many many thanks to actae0n of Blacksun Hackers Club for reporting this issue and providing examples of how it could be exploited.
|
16
16
|
|
17
|
-
## \[2.1.0] -
|
17
|
+
## \[2.1.0] - 2022-10-10
|
18
18
|
|
19
19
|
### Added
|
20
20
|
|
21
|
-
- Support for the `/v1/jamf-management-framework/redeploy/{id}` Jamf Pro API endpoint in `Jamf::Computer` and
|
21
|
+
- Support for the `/v1/jamf-management-framework/redeploy/{id}` Jamf Pro API endpoint in `Jamf::Computer` and
|
22
22
|
`Jamf::ComputerGroup`. The method `redeploy_mgmt_framework` is both a Class and an Instance method for those classes
|
23
23
|
- The instance method sends the redeployment to the single computer or all the members of the single computer group.
|
24
|
-
- The class method accepts a single id, or an array of ids.
|
24
|
+
- The class method accepts a single id, or an array of ids.
|
25
25
|
- When using `Jamf::Computer.redeploy_mgmt_framework` provide computer ids
|
26
26
|
- When using `Jamf::ComputerGroup.redeploy_mgmt_framework` provide group ids, and all members of all groups will get
|
27
27
|
the redeployment
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
- In all cases the result is a Hash of target computer ids (keys) and result value for each (Strings).
|
29
|
+
- The result is either the UUID of the sent MDM command, or an error message if the MDM command couldn't be sent.
|
30
|
+
- All the code is in the `Jamf::MacOSRedeployMgmtFramework` module, q.v. in the [rubydoc documentation](https://www.rubydoc.info/gems/ruby-jss/Jamf/MacOSRedeployMgmtFramework)
|
31
31
|
|
32
32
|
### Fixed
|
33
33
|
|
34
34
|
- A few internal rescues of a deprecated exception class
|
35
35
|
- Removed auto-loading of deprecation files; now explicitly loaded.
|
36
|
+
- A few Ruby 2 => Ruby 3 bugs - method params needing double-splats (Thanks to @Timelost for reporting this one)
|
37
|
+
- Ensure resource paths don't start with a slash
|
38
|
+
- Setting the timeouts on an existing API connection object now works.
|
36
39
|
|
37
40
|
## \[2.0.0] - 2022-09-12
|
38
41
|
|
data/bin/cgrouper
CHANGED
@@ -23,10 +23,8 @@
|
|
23
23
|
### KIND, either express or implied. See the Apache License for the specific
|
24
24
|
### language governing permissions and limitations under the Apache License.
|
25
25
|
|
26
|
-
|
27
26
|
# Create or change the membership of a computer group in the JSS
|
28
27
|
|
29
|
-
|
30
28
|
# Load in the JSS library
|
31
29
|
require 'jss-api'
|
32
30
|
|
@@ -44,9 +42,9 @@ class App
|
|
44
42
|
[-S server] [-U user] [-T timeout] [-V] [--debug]
|
45
43
|
group [-f /file/path ] [computer [computer ...]]"
|
46
44
|
|
47
|
-
ACTIONS_NEEDING_GROUP = [
|
45
|
+
ACTIONS_NEEDING_GROUP = %i[create_group rename_group delete_group add_members remove_members remove_all list_members]
|
48
46
|
|
49
|
-
ACTIONS_FOR_STATIC_GROUPS_ONLY = [
|
47
|
+
ACTIONS_FOR_STATIC_GROUPS_ONLY = %i[create_group add_members remove_members remove_all]
|
50
48
|
|
51
49
|
#####################################
|
52
50
|
### Attributes
|
@@ -57,31 +55,30 @@ class App
|
|
57
55
|
###
|
58
56
|
### set up
|
59
57
|
###
|
60
|
-
def initialize
|
61
|
-
|
58
|
+
def initialize
|
62
59
|
@debug = false
|
63
60
|
|
64
61
|
# define the options
|
65
62
|
cli_opts = GetoptLong.new(
|
66
|
-
[
|
67
|
-
[
|
68
|
-
[
|
69
|
-
[
|
70
|
-
[
|
71
|
-
[
|
72
|
-
[
|
73
|
-
[
|
74
|
-
[
|
75
|
-
[
|
76
|
-
[
|
77
|
-
[
|
78
|
-
[
|
79
|
-
[
|
80
|
-
[
|
81
|
-
[
|
82
|
-
[
|
83
|
-
[
|
84
|
-
[
|
63
|
+
['--help', '-h', '-H', GetoptLong::NO_ARGUMENT],
|
64
|
+
['--list-groups', '-L', GetoptLong::NO_ARGUMENT],
|
65
|
+
['--list-static', '-s', GetoptLong::NO_ARGUMENT],
|
66
|
+
['--list-smart', '-m', GetoptLong::NO_ARGUMENT],
|
67
|
+
['--create-group', '--create', '-c', GetoptLong::NO_ARGUMENT],
|
68
|
+
['--rename-group', '--rename', '-n', GetoptLong::REQUIRED_ARGUMENT],
|
69
|
+
['--delete-group', '--delete', '-d', GetoptLong::NO_ARGUMENT],
|
70
|
+
['--list-members', '--list-computers', '-l', GetoptLong::NO_ARGUMENT],
|
71
|
+
['--add-members', '--add', '-a', GetoptLong::NO_ARGUMENT],
|
72
|
+
['--remove-members', '--remove', '-r', GetoptLong::NO_ARGUMENT],
|
73
|
+
['--remove-all-members', '-R', GetoptLong::NO_ARGUMENT],
|
74
|
+
['--file', '-f', GetoptLong::REQUIRED_ARGUMENT],
|
75
|
+
['--server', '-S', GetoptLong::OPTIONAL_ARGUMENT],
|
76
|
+
['--port', '-P', GetoptLong::OPTIONAL_ARGUMENT],
|
77
|
+
['--user', '-U', GetoptLong::OPTIONAL_ARGUMENT],
|
78
|
+
['--no-verify-cert', '-V', GetoptLong::NO_ARGUMENT],
|
79
|
+
['--timeout', '-T', GetoptLong::OPTIONAL_ARGUMENT],
|
80
|
+
['--no-confirm', '-C', GetoptLong::NO_ARGUMENT],
|
81
|
+
['--debug', GetoptLong::NO_ARGUMENT]
|
85
82
|
)
|
86
83
|
|
87
84
|
# here's where we hold cmdline args and other user options
|
@@ -92,68 +89,68 @@ class App
|
|
92
89
|
|
93
90
|
# if stdin is not a tty, then we must assume
|
94
91
|
# we're being passed a password
|
95
|
-
@options.getpass =
|
92
|
+
@options.getpass = $stdin.tty? ? :prompt : :stdin
|
96
93
|
|
97
94
|
# parse the options
|
98
95
|
cli_opts.each do |opt, arg|
|
99
96
|
case opt
|
100
|
-
|
101
|
-
|
97
|
+
when '--help'
|
98
|
+
show_help
|
102
99
|
|
103
|
-
|
104
|
-
|
100
|
+
when '--list-groups'
|
101
|
+
@options.action = :list_groups
|
105
102
|
|
106
|
-
|
107
|
-
|
103
|
+
when '--list-static'
|
104
|
+
@options.action = :list_static
|
108
105
|
|
109
|
-
|
110
|
-
|
106
|
+
when '--list-smart'
|
107
|
+
@options.action = :list_smart
|
111
108
|
|
112
|
-
|
113
|
-
|
109
|
+
when '--list-members'
|
110
|
+
@options.action = :list_members
|
114
111
|
|
115
|
-
|
116
|
-
|
112
|
+
when '--create-group'
|
113
|
+
@options.action = :create_group
|
117
114
|
|
118
|
-
|
119
|
-
|
120
|
-
|
115
|
+
when '--rename-group'
|
116
|
+
@options.action = :rename_group
|
117
|
+
@options.new_name = arg
|
121
118
|
|
122
|
-
|
123
|
-
|
119
|
+
when '--delete-group'
|
120
|
+
@options.action = :delete_group
|
124
121
|
|
125
|
-
|
126
|
-
|
122
|
+
when '--add-members'
|
123
|
+
@options.action = :add_members
|
127
124
|
|
128
|
-
|
129
|
-
|
125
|
+
when '--remove-members'
|
126
|
+
@options.action = :remove_members
|
130
127
|
|
131
|
-
|
132
|
-
|
128
|
+
when '--remove-all-members'
|
129
|
+
@options.action = :remove_all
|
133
130
|
|
134
|
-
|
135
|
-
|
131
|
+
when '--file'
|
132
|
+
@options.input_file = Pathname.new arg
|
136
133
|
|
137
|
-
|
138
|
-
|
134
|
+
when '--server'
|
135
|
+
@options.server = arg
|
139
136
|
|
140
|
-
|
141
|
-
|
137
|
+
when '--port'
|
138
|
+
@options.port = arg
|
142
139
|
|
143
|
-
|
144
|
-
|
140
|
+
when '--user'
|
141
|
+
@options.user = arg
|
145
142
|
|
146
|
-
|
147
|
-
|
143
|
+
when '--no-verify-cert'
|
144
|
+
@options.verify_cert = false
|
148
145
|
|
149
|
-
|
150
|
-
|
146
|
+
when '--timeout'
|
147
|
+
@options.timeout = arg
|
151
148
|
|
152
|
-
|
153
|
-
|
149
|
+
when '--no-confirm'
|
150
|
+
@options.no_confirm = true
|
154
151
|
|
155
|
-
|
156
|
-
|
152
|
+
when '--debug'
|
153
|
+
@debug = true
|
157
154
|
|
158
155
|
end # case
|
159
156
|
end # opts.each
|
@@ -168,17 +165,13 @@ class App
|
|
168
165
|
|
169
166
|
# will we say anything when finished?
|
170
167
|
@done_msg = nil
|
171
|
-
|
172
168
|
end # init
|
173
169
|
|
174
|
-
|
175
|
-
|
176
170
|
#####################################
|
177
171
|
###
|
178
172
|
### Do It
|
179
173
|
###
|
180
174
|
def run
|
181
|
-
|
182
175
|
if @options.action == :none
|
183
176
|
puts USAGE
|
184
177
|
return
|
@@ -188,75 +181,73 @@ class App
|
|
188
181
|
@options.user ||= JSS::CONFIG.api_username
|
189
182
|
@options.server ||= JSS::CONFIG.api_server_name
|
190
183
|
|
191
|
-
raise JSS::MissingDataError,
|
192
|
-
raise JSS::MissingDataError,
|
193
|
-
|
194
|
-
Jamf.cnx.connect( :server => @options.server,
|
195
|
-
:port => @options.port,
|
196
|
-
:verify_cert => @options.verify_cert,
|
197
|
-
:user => @options.user,
|
198
|
-
:pw => @options.getpass,
|
199
|
-
:stdin_line => 1,
|
200
|
-
:timeout => @options.timeout
|
201
|
-
)
|
184
|
+
raise JSS::MissingDataError, 'No JSS Username provided or found in the JSS gem config.' unless @options.user
|
185
|
+
raise JSS::MissingDataError, 'No JSS Server provided or found in the JSS gem config.' unless @options.server
|
202
186
|
|
187
|
+
Jamf.cnx.connect(server: @options.server,
|
188
|
+
port: @options.port,
|
189
|
+
verify_cert: @options.verify_cert,
|
190
|
+
user: @options.user,
|
191
|
+
pw: @options.getpass,
|
192
|
+
stdin_line: 1,
|
193
|
+
timeout: @options.timeout)
|
203
194
|
|
204
195
|
if ACTIONS_NEEDING_GROUP.include? @options.action
|
205
196
|
|
206
|
-
raise JSS::MissingDataError,
|
197
|
+
raise JSS::MissingDataError, 'Please specify a group name' unless @options.group
|
207
198
|
|
208
|
-
|
209
|
-
if @options.action == :create_group
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
199
|
+
# get the group from the API
|
200
|
+
@group = if @options.action == :create_group
|
201
|
+
JSS::ComputerGroup.make name: @options.group, type: :static
|
202
|
+
else
|
203
|
+
JSS::ComputerGroup.fetch name: @options.group
|
204
|
+
end
|
214
205
|
|
215
206
|
end # if ACTIONS_NEEDING_GROUP
|
216
207
|
|
217
208
|
# smart groups can't have some things done to them
|
218
|
-
|
219
|
-
|
209
|
+
if ACTIONS_FOR_STATIC_GROUPS_ONLY.include? @options.action and @group.smart?
|
210
|
+
raise InvalidTypeError,
|
211
|
+
"You can't do that to a smart group. Use the JSS WebApp if needed."
|
212
|
+
end
|
220
213
|
|
221
214
|
case @options.action
|
222
215
|
|
223
|
-
|
224
|
-
|
216
|
+
when :list_groups
|
217
|
+
list_groups
|
225
218
|
|
226
|
-
|
227
|
-
|
219
|
+
when :list_static
|
220
|
+
list_groups :static
|
228
221
|
|
229
|
-
|
230
|
-
|
222
|
+
when :list_smart
|
223
|
+
list_groups :smart
|
231
224
|
|
232
|
-
|
233
|
-
|
225
|
+
when :list_members
|
226
|
+
list_members
|
234
227
|
|
235
|
-
|
236
|
-
|
228
|
+
when :create_group
|
229
|
+
create_group
|
237
230
|
|
238
|
-
|
239
|
-
|
231
|
+
when :rename_group
|
232
|
+
rename_group
|
240
233
|
|
241
|
-
|
242
|
-
|
234
|
+
when :delete_group
|
235
|
+
delete_group
|
243
236
|
|
244
|
-
|
245
|
-
|
237
|
+
when :add_members
|
238
|
+
add_members
|
246
239
|
|
247
|
-
|
248
|
-
|
240
|
+
when :remove_members
|
241
|
+
remove_members
|
249
242
|
|
250
|
-
|
251
|
-
|
243
|
+
when :remove_all
|
244
|
+
remove_all
|
252
245
|
|
253
246
|
end # case @options.action
|
254
247
|
|
255
248
|
puts "Done! #{@done_msg}" if @done_msg
|
256
|
-
|
257
249
|
end # run
|
258
250
|
|
259
|
-
|
260
251
|
#####################################
|
261
252
|
###
|
262
253
|
### Show Help
|
@@ -307,7 +298,6 @@ Notes:
|
|
307
298
|
(spaces, tabs, & returns in any number or combination)
|
308
299
|
|
309
300
|
FULLHELP
|
310
|
-
|
311
301
|
end
|
312
302
|
|
313
303
|
#####################################
|
@@ -316,21 +306,21 @@ Notes:
|
|
316
306
|
###
|
317
307
|
def list_groups(show = :all)
|
318
308
|
case show
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
end #case
|
309
|
+
when :all
|
310
|
+
label = 'All'
|
311
|
+
groups_to_show = JSS::ComputerGroup.all
|
312
|
+
when :static
|
313
|
+
label = 'Static'
|
314
|
+
groups_to_show = JSS::ComputerGroup.all_static
|
315
|
+
when :smart
|
316
|
+
label = 'Smart'
|
317
|
+
groups_to_show = JSS::ComputerGroup.all_smart
|
318
|
+
end # case
|
329
319
|
|
330
320
|
puts "# #{label} computer groups in the JSS"
|
331
|
-
puts
|
321
|
+
puts '#---------------------------------------------'
|
332
322
|
|
333
|
-
groups_to_show.sort{|a,b| a[:name].downcase <=> b[:name].downcase}.each do |grp|
|
323
|
+
groups_to_show.sort { |a, b| a[:name].downcase <=> b[:name].downcase }.each do |grp|
|
334
324
|
puts grp[:name]
|
335
325
|
end
|
336
326
|
end
|
@@ -341,30 +331,26 @@ Notes:
|
|
341
331
|
###
|
342
332
|
def list_members
|
343
333
|
puts "# All members of JSS #{@group.smart? ? 'smart' : 'static'} computer group '#{@options.group}'"
|
344
|
-
puts
|
334
|
+
puts '#--- name (id) ---------------------------------'
|
345
335
|
|
346
336
|
# put them into a tmp array, so that
|
347
337
|
# we can sort by computer name, remembering that
|
348
338
|
# there can be duplicate names.
|
349
339
|
list = []
|
350
|
-
@group.members.each{|mem| list << "#{mem[:name]} (#{mem[:id]})" }
|
351
|
-
puts list.sort
|
340
|
+
@group.members.each { |mem| list << "#{mem[:name]} (#{mem[:id]})" }
|
341
|
+
puts list.sort # .join("\n")
|
352
342
|
end
|
353
343
|
|
354
|
-
|
355
344
|
#####################################
|
356
345
|
###
|
357
346
|
### Create a new group
|
358
347
|
###
|
359
348
|
def create_group
|
360
|
-
|
361
349
|
return unless confirm "create a new static group named '#{@options.group}'"
|
362
|
-
@group.create
|
363
350
|
|
364
|
-
|
365
|
-
add_members
|
366
|
-
end
|
351
|
+
@group.create
|
367
352
|
|
353
|
+
add_members unless @options.computers.empty?
|
368
354
|
end
|
369
355
|
|
370
356
|
#####################################
|
@@ -373,36 +359,35 @@ Notes:
|
|
373
359
|
###
|
374
360
|
def rename_group
|
375
361
|
return unless confirm "rename group '#{@group.name}' to '#{@options.new_name}'"
|
362
|
+
|
376
363
|
@group.name = @options.new_name
|
377
364
|
@group.update
|
378
365
|
end
|
379
366
|
|
380
|
-
|
381
367
|
#####################################
|
382
368
|
###
|
383
369
|
### delete a group
|
384
370
|
###
|
385
371
|
def delete_group
|
386
372
|
return unless confirm "DELETE group '#{@group.name}'"
|
373
|
+
|
387
374
|
@group.delete
|
388
375
|
end
|
389
376
|
|
390
|
-
|
391
377
|
#####################################
|
392
378
|
###
|
393
379
|
### add members to a group
|
394
380
|
###
|
395
381
|
def add_members
|
396
|
-
raise JSS::MissingDataError,
|
382
|
+
raise JSS::MissingDataError, 'No computer names provided' if @options.computers.empty?
|
397
383
|
raise JSS::UnsupportedError, "Smart group members can't be changed." if @group.smart?
|
398
384
|
return unless @options.action == :create_group or confirm "add computers to group '#{@group.name}'"
|
399
385
|
|
400
386
|
@options.computers.each do |c|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
end # begin
|
387
|
+
@group.add_member c
|
388
|
+
rescue JSS::NoSuchItemError
|
389
|
+
puts "#{$!} - skipping"
|
390
|
+
# begin
|
406
391
|
end # each
|
407
392
|
|
408
393
|
@group.update
|
@@ -413,15 +398,14 @@ Notes:
|
|
413
398
|
### remove members from a group
|
414
399
|
###
|
415
400
|
def remove_members
|
416
|
-
raise JSS::MissingDataError,
|
401
|
+
raise JSS::MissingDataError, 'No computer names provided' if @options.computers.empty?
|
417
402
|
raise JSS::UnsupportedError, "Smart group members can't be changed." if @group.smart?
|
418
403
|
return unless confirm "remove computers from group '#{@group.name}'"
|
404
|
+
|
419
405
|
@options.computers.each do |c|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
puts "#{$!} - skipping"
|
424
|
-
end
|
406
|
+
@group.remove_member c
|
407
|
+
rescue JSS::NoSuchItemError
|
408
|
+
puts "#{$!} - skipping"
|
425
409
|
end
|
426
410
|
@group.update
|
427
411
|
end
|
@@ -433,11 +417,11 @@ Notes:
|
|
433
417
|
def remove_all
|
434
418
|
raise JSS::UnsupportedError, "Smart group members can't be changed." if @group.smart?
|
435
419
|
return unless confirm "remove ALL computers from group '#{@group.name}'"
|
420
|
+
|
436
421
|
@group.clear
|
437
422
|
@group.update
|
438
423
|
end
|
439
424
|
|
440
|
-
|
441
425
|
#####################################
|
442
426
|
###
|
443
427
|
### Read computer names from a file
|
@@ -448,6 +432,7 @@ Notes:
|
|
448
432
|
def get_computers_from_file
|
449
433
|
raise JSS::NoSuchItemError "File #{@options.input_file} isn't a file or isn't readable." unless \
|
450
434
|
@options.input_file.file? and @options.input_file.readable?
|
435
|
+
|
451
436
|
@options.input_file.read.split(/\s+/)
|
452
437
|
end
|
453
438
|
|
@@ -456,31 +441,26 @@ Notes:
|
|
456
441
|
### Get confirmation before doing something
|
457
442
|
### Returns true or false
|
458
443
|
###
|
459
|
-
def confirm
|
460
|
-
|
444
|
+
def confirm(action)
|
445
|
+
return true if @options.no_confirm
|
461
446
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
return false
|
447
|
+
print "Really #{action}? (y/n): "
|
448
|
+
$stdin.reopen '/dev/tty'
|
449
|
+
reply = $stdin.gets.strip
|
450
|
+
return true if reply =~ /^y/i
|
467
451
|
|
452
|
+
false
|
468
453
|
end # confirm
|
469
454
|
|
470
|
-
|
471
455
|
end # class App
|
472
456
|
|
473
457
|
#######################################
|
474
458
|
begin
|
475
|
-
app = App.new
|
459
|
+
app = App.new
|
476
460
|
app.run
|
477
|
-
|
478
461
|
rescue
|
479
462
|
# handle exceptions not handled elsewhere
|
480
463
|
puts "An error occurred: #{$!}"
|
481
|
-
puts
|
464
|
+
puts 'Backtrace:' if app.debug
|
482
465
|
puts $@ if app.debug
|
483
|
-
|
484
|
-
ensure
|
485
|
-
|
486
466
|
end
|
data/bin/jamfHelperBackgrounder
CHANGED
@@ -53,7 +53,7 @@ class App
|
|
53
53
|
|
54
54
|
# Set up
|
55
55
|
#
|
56
|
-
def initialize(args)
|
56
|
+
def initialize(**args)
|
57
57
|
if args.include? '-help'
|
58
58
|
@help = true
|
59
59
|
return
|
@@ -66,6 +66,7 @@ class App
|
|
66
66
|
|
67
67
|
wintype_idx = args.index { |a| a == WIN_TYPE_PARAM }
|
68
68
|
raise 'missing option: -windowType' unless wintype_idx
|
69
|
+
|
69
70
|
args.delete_at wintype_idx
|
70
71
|
@window_type = args.delete_at(wintype_idx).to_sym
|
71
72
|
|
@@ -93,6 +94,7 @@ class App
|
|
93
94
|
|
94
95
|
if @as_user
|
95
96
|
raise 'Only root can do things as another user' unless JSS.superuser?
|
97
|
+
|
96
98
|
cmd = ['su', '-l', @as_user, '-c', "#{Shellwords.escape __FILE__} #{@arg_string}"]
|
97
99
|
exec(*cmd)
|
98
100
|
end
|
@@ -134,7 +136,7 @@ This command takes all the same commandline options as jamfHelper, plus these:
|
|
134
136
|
WARNING: You shouldn't run this command directly as a launchd job. Rather
|
135
137
|
you should write a small script that runs this command, and use launchd
|
136
138
|
to run that.
|
137
|
-
ENDHELP
|
139
|
+
ENDHELP
|
138
140
|
end # show help
|
139
141
|
|
140
142
|
end # app
|
data/bin/netseg-update
CHANGED
@@ -55,13 +55,13 @@ class App
|
|
55
55
|
|
56
56
|
USAGE = "Usage: #{PROG_NAME} [options] [--help] /path/to/file".freeze
|
57
57
|
|
58
|
-
POTENTIAL_COLUMNS = %i
|
58
|
+
POTENTIAL_COLUMNS = %i[name starting ending cidr mask].freeze
|
59
59
|
|
60
60
|
DEFAULT_CACHE_FILE = Pathname.new('~/.last_subnet_update').expand_path
|
61
61
|
|
62
62
|
DEFAULT_DELIMITER = "\t".freeze
|
63
63
|
|
64
|
-
DEFAULT_COLUMNS = [
|
64
|
+
DEFAULT_COLUMNS = %i[name starting ending].freeze
|
65
65
|
|
66
66
|
DEFAULT_MANUAL_PREFIX = 'Manual-'.freeze
|
67
67
|
|
@@ -84,7 +84,7 @@ class App
|
|
84
84
|
|
85
85
|
attr_reader :debug
|
86
86
|
|
87
|
-
def initialize
|
87
|
+
def initialize
|
88
88
|
@getpass = $stdin.tty? ? :prompt : :stdin
|
89
89
|
set_defaults
|
90
90
|
parse_cli
|
@@ -183,7 +183,7 @@ Options:
|
|
183
183
|
-V, --no-verify-cert - Allow self-signed, unverified SSL certificate
|
184
184
|
-T, --timeout secs - specify the JSS API timeout
|
185
185
|
-N, --no-op - Don't make any changes in the JSS, just report what would
|
186
|
-
have
|
186
|
+
have been changed.
|
187
187
|
-H, --help - show this help
|
188
188
|
--debug - show the ruby backtrace when errors occur
|
189
189
|
|
@@ -254,6 +254,7 @@ Notes:
|
|
254
254
|
lines.each do |line|
|
255
255
|
parsed_line = parse_a_data_line line
|
256
256
|
next unless parsed_line
|
257
|
+
|
257
258
|
name = parsed_line.delete :name
|
258
259
|
parsed_data[name] = parsed_line
|
259
260
|
end
|
@@ -273,6 +274,7 @@ Notes:
|
|
273
274
|
@columns.include?(:ending) || \
|
274
275
|
@columns.include?(:cidr) || \
|
275
276
|
@columns.include?(:mask)
|
277
|
+
|
276
278
|
@use_cidr = (@columns.include?(:cidr) || @columns.include?(:mask))
|
277
279
|
end
|
278
280
|
|
@@ -296,11 +298,13 @@ Notes:
|
|
296
298
|
# read in the file
|
297
299
|
@raw_data = @file.read
|
298
300
|
return true unless @cache_file.exist?
|
301
|
+
|
299
302
|
@raw_data != @cache_file.read
|
300
303
|
end
|
301
304
|
|
302
305
|
def cache_latest_data
|
303
306
|
return if @noop
|
307
|
+
|
304
308
|
@cache_file.jss_save @raw_data
|
305
309
|
end
|
306
310
|
|
@@ -375,7 +379,7 @@ end # app
|
|
375
379
|
# create the app and go
|
376
380
|
begin
|
377
381
|
debug = ARGV.include? '--debug'
|
378
|
-
app = App.new
|
382
|
+
app = App.new
|
379
383
|
app.run
|
380
384
|
rescue
|
381
385
|
# handle exceptions not handled elsewhere
|
@@ -440,7 +440,7 @@ module Jamf
|
|
440
440
|
cnx = api if api
|
441
441
|
|
442
442
|
id = valid_id ident, cnx: cnx
|
443
|
-
raise "No computer matches identifier: #{ident}" unless id
|
443
|
+
raise Jamf::NoSuchItemError, "No computer matches identifier: #{ident}" unless id
|
444
444
|
|
445
445
|
end_date ||= start_date
|
446
446
|
start_date = Jamf.parse_time start_date
|
@@ -154,7 +154,7 @@ module Jamf
|
|
154
154
|
# when fetching a specific version, this is a valid version
|
155
155
|
UNKNOWN_VERSION_ID = 'Unknown'.freeze
|
156
156
|
|
157
|
-
REPORTS_RSRC_BASE = '
|
157
|
+
REPORTS_RSRC_BASE = 'patchreports/patchsoftwaretitleid'.freeze
|
158
158
|
|
159
159
|
# Class Methods
|
160
160
|
#######################################
|
@@ -233,7 +233,7 @@ module Jamf
|
|
233
233
|
all(refresh, cnx: cnx).map { |i| i[:source_name_id] }
|
234
234
|
end
|
235
235
|
|
236
|
-
# Get a patch report for a softwaretitle,
|
236
|
+
# Get a patch report for a softwaretitle, without fetching an instance.
|
237
237
|
# Defaults to reporting all versions. Specifiying a version will be faster.
|
238
238
|
#
|
239
239
|
# The Hash returned has 3 keys:
|
@@ -269,6 +269,7 @@ module Jamf
|
|
269
269
|
|
270
270
|
# TODO: remove this and adjust parsing when jamf fixes the JSON
|
271
271
|
raw_report = XMLWorkaround.data_via_xml(rsrc, PATCH_REPORT_DATA_MAP, cnx)[:patch_report]
|
272
|
+
|
272
273
|
report = {}
|
273
274
|
report[:total_computers] = raw_report[:total_computers]
|
274
275
|
report[:total_versions] = raw_report[:total_versions]
|
@@ -312,7 +313,7 @@ module Jamf
|
|
312
313
|
# so all other lookup values have to be converted to ID before
|
313
314
|
# the call to super
|
314
315
|
#
|
315
|
-
def self.fetch(identifier = nil, **params)
|
316
|
+
def self.fetch(identifier = nil, **params)
|
316
317
|
# default connection if unspecified
|
317
318
|
cnx = params.delete :cnx
|
318
319
|
cnx ||= params.delete :api # backward compatibility, deprecated
|
@@ -472,7 +473,6 @@ module Jamf
|
|
472
473
|
# wrapper to fetch versions after creating
|
473
474
|
def create
|
474
475
|
super
|
475
|
-
|
476
476
|
end
|
477
477
|
|
478
478
|
# wrapper to clear @changed_pkgs after updating
|
@@ -150,7 +150,8 @@ module Jamf
|
|
150
150
|
element ? element.text.to_f : model
|
151
151
|
when nil
|
152
152
|
return nil unless element
|
153
|
-
|
153
|
+
|
154
|
+
element.text.downcase == TRUE_STRING
|
154
155
|
when Array
|
155
156
|
element ? elem_as_array(model.first, element) : []
|
156
157
|
when Hash
|
@@ -176,6 +177,7 @@ module Jamf
|
|
176
177
|
return unless size_elems.count == 1
|
177
178
|
return if size_elem.has_elements?
|
178
179
|
return unless size_elem.text.jss_integer?
|
180
|
+
|
179
181
|
elem.delete_element size_elem
|
180
182
|
end
|
181
183
|
|
@@ -74,15 +74,15 @@ module Jamf
|
|
74
74
|
attr_reader :sticky_session
|
75
75
|
alias sticky_session? sticky_session
|
76
76
|
alias sticky? sticky_session
|
77
|
-
|
77
|
+
|
78
78
|
# @return [String, nil] The current sticky_session cookie. nil unless
|
79
79
|
# sticky_session is set to true, either as a param to 'connect' or via
|
80
80
|
# #sticky_session=
|
81
81
|
#
|
82
|
-
# When set via .connect, the cookie is gleaned from the token creation
|
82
|
+
# When set via .connect, the cookie is gleaned from the token creation
|
83
83
|
# reponse. When set via #sticky_session=, a HEAD request is made, and the
|
84
84
|
# cookie will be in the response.
|
85
|
-
#
|
85
|
+
#
|
86
86
|
# Only valid when the connection is to a Jamf Cloud server.
|
87
87
|
attr_reader :sticky_session_cookie
|
88
88
|
|
@@ -100,7 +100,7 @@ module Jamf
|
|
100
100
|
|
101
101
|
# convert boolean-y to boolean
|
102
102
|
value = value ? true : false
|
103
|
-
|
103
|
+
|
104
104
|
return if @sticky_session == value
|
105
105
|
|
106
106
|
if value
|
@@ -125,8 +125,8 @@ module Jamf
|
|
125
125
|
#
|
126
126
|
def timeout=(new_timeout)
|
127
127
|
@timeout = new_timeout.to_i
|
128
|
-
@c_cnx
|
129
|
-
@jp_cnx
|
128
|
+
@c_cnx.options.timeout = @timeout if @c_cnx
|
129
|
+
@jp_cnx.options.timeout = @timeout if @jp_cnx
|
130
130
|
end
|
131
131
|
|
132
132
|
# Reset the open-connection timeout for the rest connection
|
@@ -137,8 +137,8 @@ module Jamf
|
|
137
137
|
#
|
138
138
|
def open_timeout=(new_timeout)
|
139
139
|
@open_timeout = new_timeout.to_i
|
140
|
-
@c_cnx
|
141
|
-
@jp_cnx
|
140
|
+
@c_cnx.options.open_timeout = @open_timeout if @c_cnx
|
141
|
+
@jp_cnx.options.open_timeout = @open_timeout if @jp_cnx
|
142
142
|
end
|
143
143
|
|
144
144
|
# @return [URI::HTTPS] the base URL to the server
|
@@ -59,6 +59,8 @@ module Jamf
|
|
59
59
|
# @return [Hash,String] the result of the get
|
60
60
|
#
|
61
61
|
def c_get(rsrc, format = :json, raw_json: false)
|
62
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
63
|
+
|
62
64
|
validate_connected @c_cnx
|
63
65
|
raise Jamf::InvalidDataError, 'format must be :json or :xml' unless Jamf::Connection::GET_FORMATS.include?(format)
|
64
66
|
|
@@ -92,6 +94,8 @@ module Jamf
|
|
92
94
|
def c_post(rsrc, xml)
|
93
95
|
validate_connected @c_cnx
|
94
96
|
|
97
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
98
|
+
|
95
99
|
# convert CRs & to
|
96
100
|
xml&.gsub!(/\r/, ' ')
|
97
101
|
|
@@ -125,6 +129,8 @@ module Jamf
|
|
125
129
|
def c_put(rsrc, xml)
|
126
130
|
validate_connected @c_cnx
|
127
131
|
|
132
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
133
|
+
|
128
134
|
# convert CRs & to
|
129
135
|
xml.gsub!(/\r/, ' ')
|
130
136
|
|
@@ -157,6 +163,8 @@ module Jamf
|
|
157
163
|
validate_connected @c_cnx
|
158
164
|
raise MissingDataError, 'Missing :rsrc' if rsrc.nil?
|
159
165
|
|
166
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
167
|
+
|
160
168
|
# delete the resource
|
161
169
|
resp =
|
162
170
|
@c_cnx.delete(rsrc) do |req|
|
@@ -188,6 +196,7 @@ module Jamf
|
|
188
196
|
#
|
189
197
|
def upload(rsrc, local_file)
|
190
198
|
validate_connected @c_cnx
|
199
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
191
200
|
|
192
201
|
# the upload file object for faraday
|
193
202
|
local_file = Pathname.new local_file
|
@@ -223,7 +232,7 @@ module Jamf
|
|
223
232
|
|
224
233
|
cnx.options[:timeout] = @timeout
|
225
234
|
cnx.options[:open_timeout] = @open_timeout
|
226
|
-
|
235
|
+
|
227
236
|
cnx.request :multipart
|
228
237
|
cnx.request :url_encoded
|
229
238
|
|
@@ -53,11 +53,12 @@ module Jamf
|
|
53
53
|
|
54
54
|
# @param rsrc[String] the resource to get
|
55
55
|
# (the part of the API url after the '/api/' )
|
56
|
-
|
56
|
+
|
57
57
|
# @return [Hash] the result of the get
|
58
58
|
#######################################################
|
59
59
|
def jp_get(rsrc)
|
60
60
|
validate_connected @jp_cnx
|
61
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
61
62
|
resp = @jp_cnx.get(rsrc) do |req|
|
62
63
|
# Modify the request here if needed.
|
63
64
|
# puts "JPAPI Cookie is: #{req.headers['Cookie']}"
|
@@ -82,6 +83,7 @@ module Jamf
|
|
82
83
|
#######################################################
|
83
84
|
def jp_post(rsrc, data)
|
84
85
|
validate_connected @jp_cnx
|
86
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
85
87
|
resp = @jp_cnx.post(rsrc) do |req|
|
86
88
|
req.body = data
|
87
89
|
end
|
@@ -104,6 +106,7 @@ module Jamf
|
|
104
106
|
#######################################################
|
105
107
|
def jp_put(rsrc, data)
|
106
108
|
validate_connected @jp_cnx
|
109
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
107
110
|
resp = @jp_cnx.put(rsrc) do |req|
|
108
111
|
req.body = data
|
109
112
|
end
|
@@ -126,6 +129,7 @@ module Jamf
|
|
126
129
|
#######################################################
|
127
130
|
def jp_patch(rsrc, data)
|
128
131
|
validate_connected @jp_cnx
|
132
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
129
133
|
resp = @jp_cnx.patch(rsrc) do |req|
|
130
134
|
req.body = data
|
131
135
|
end
|
@@ -146,6 +150,7 @@ module Jamf
|
|
146
150
|
#######################################################
|
147
151
|
def jp_delete(rsrc)
|
148
152
|
validate_connected @jp_cnx
|
153
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
149
154
|
resp = @jp_cnx.delete rsrc
|
150
155
|
@last_http_response = resp
|
151
156
|
return resp.body if resp.success?
|
@@ -159,6 +164,7 @@ module Jamf
|
|
159
164
|
# a temporary Faraday connection object
|
160
165
|
#######################################################
|
161
166
|
def jp_download(rsrc)
|
167
|
+
rsrc = rsrc.delete_prefix Jamf::Connection::SLASH
|
162
168
|
temp_cnx = create_jp_connection(parse_json: false)
|
163
169
|
resp = temp_cnx.get rsrc
|
164
170
|
@last_http_response = resp
|
data/lib/jamf/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-jss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Lasell
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-10-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: CFPropertyList
|
@@ -824,9 +824,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
824
824
|
version: 2.6.3
|
825
825
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
826
826
|
requirements:
|
827
|
-
- - "
|
827
|
+
- - ">="
|
828
828
|
- !ruby/object:Gem::Version
|
829
|
-
version:
|
829
|
+
version: '0'
|
830
830
|
requirements: []
|
831
831
|
rubygems_version: 3.0.3.1
|
832
832
|
signing_key:
|