ruby-jss 0.7.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-jss might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGES.md +29 -22
- data/README.md +66 -86
- data/bin/jamfHelperBackgrounder +148 -0
- data/bin/netseg-update +0 -1
- data/lib/jss.rb +20 -9
- data/lib/jss/api_connection.rb +369 -295
- data/lib/jss/api_object.rb +651 -418
- data/lib/jss/api_object/account.rb +69 -77
- data/lib/jss/api_object/advanced_search.rb +201 -236
- data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +42 -42
- data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +33 -43
- data/lib/jss/api_object/advanced_search/advanced_user_search.rb +33 -43
- data/lib/jss/api_object/building.rb +39 -52
- data/lib/jss/api_object/categorizable.rb +221 -0
- data/lib/jss/api_object/category.rb +81 -89
- data/lib/jss/api_object/computer.rb +486 -525
- data/lib/jss/api_object/computer_invitation.rb +73 -86
- data/lib/jss/api_object/criteriable.rb +6 -7
- data/lib/jss/api_object/ebook.rb +21 -0
- data/lib/jss/api_object/extendable.rb +6 -8
- data/lib/jss/api_object/group.rb +0 -3
- data/lib/jss/api_object/locatable.rb +19 -20
- data/lib/jss/api_object/mac_application.rb +21 -0
- data/lib/jss/api_object/mobile_device.rb +30 -21
- data/lib/jss/api_object/mobile_device_application.rb +447 -0
- data/lib/jss/api_object/mobile_device_configuration_profile.rb +21 -0
- data/lib/jss/api_object/osx_configuration_profile.rb +0 -3
- data/lib/jss/api_object/package.rb +21 -34
- data/lib/jss/api_object/peripheral.rb +16 -18
- data/lib/jss/api_object/policy.rb +5 -83
- data/lib/jss/api_object/purchasable.rb +11 -13
- data/lib/jss/api_object/scopable.rb +11 -12
- data/lib/jss/api_object/script.rb +3 -17
- data/lib/jss/api_object/self_servable.rb +419 -205
- data/lib/jss/api_object/self_servable/icon.rb +179 -0
- data/lib/jss/api_object/updatable.rb +35 -34
- data/lib/jss/api_object/uploadable.rb +72 -70
- data/lib/jss/api_object/user.rb +6 -7
- data/lib/jss/api_object/vppable.rb +117 -0
- data/lib/jss/client.rb +264 -225
- data/lib/jss/db_connection.rb +7 -5
- data/lib/jss/exceptions.rb +50 -42
- data/lib/jss/ruby_extensions.rb +8 -7
- data/lib/jss/ruby_extensions/object.rb +19 -0
- data/lib/jss/utility.rb +82 -40
- data/lib/jss/version.rb +1 -1
- metadata +37 -68
- data/bin/jss-webhook-server +0 -3
- data/lib/jss/webhooks.rb +0 -53
- data/lib/jss/webhooks/README.md +0 -269
- data/lib/jss/webhooks/configuration.rb +0 -213
- data/lib/jss/webhooks/data/sample_handlers/RestAPIOperation-executable +0 -91
- data/lib/jss/webhooks/data/sample_handlers/RestAPIOperation.rb +0 -45
- data/lib/jss/webhooks/data/sample_jsons/ComputerAdded.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerCheckIn.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerInventoryCompleted.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerPolicyFinished.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerPushCapabilityChanged.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/JSSShutdown.json +0 -14
- data/lib/jss/webhooks/data/sample_jsons/JSSStartup.json +0 -14
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceCheckIn.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceCommandCompleted.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceEnrolled.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDevicePushSent.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceUnEnrolled.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/PatchSoftwareTitleUpdated.json +0 -14
- data/lib/jss/webhooks/data/sample_jsons/PushSent.json +0 -11
- data/lib/jss/webhooks/data/sample_jsons/RestAPIOperation.json +0 -15
- data/lib/jss/webhooks/data/sample_jsons/SCEPChallenge.json +0 -10
- data/lib/jss/webhooks/data/sample_jsons/SmartGroupComputerMembershipChange.json +0 -13
- data/lib/jss/webhooks/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +0 -13
- data/lib/jss/webhooks/event.rb +0 -139
- data/lib/jss/webhooks/event/computer_added.rb +0 -38
- data/lib/jss/webhooks/event/computer_check_in.rb +0 -38
- data/lib/jss/webhooks/event/computer_inventory_completed.rb +0 -38
- data/lib/jss/webhooks/event/computer_policy_finished.rb +0 -38
- data/lib/jss/webhooks/event/computer_push_capability_changed.rb +0 -38
- data/lib/jss/webhooks/event/handlers.rb +0 -192
- data/lib/jss/webhooks/event/jss_shutdown.rb +0 -38
- data/lib/jss/webhooks/event/jss_startup.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_check_in.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_command_completed.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_enrolled.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_push_sent.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_unenrolled.rb +0 -38
- data/lib/jss/webhooks/event/patch_software_title_updated.rb +0 -38
- data/lib/jss/webhooks/event/push_sent.rb +0 -38
- data/lib/jss/webhooks/event/rest_api_operation.rb +0 -38
- data/lib/jss/webhooks/event/scep_challenge.rb +0 -38
- data/lib/jss/webhooks/event/smart_group_computer_membership_change.rb +0 -38
- data/lib/jss/webhooks/event/smart_group_mobile_device_membership_change.rb +0 -38
- data/lib/jss/webhooks/event/webhook.rb +0 -40
- data/lib/jss/webhooks/event_objects.rb +0 -112
- data/lib/jss/webhooks/event_objects/computer.rb +0 -49
- data/lib/jss/webhooks/event_objects/jss.rb +0 -36
- data/lib/jss/webhooks/event_objects/mobile_device.rb +0 -48
- data/lib/jss/webhooks/event_objects/patch_software_title_update.rb +0 -38
- data/lib/jss/webhooks/event_objects/push.rb +0 -33
- data/lib/jss/webhooks/event_objects/rest_api_operation.rb +0 -37
- data/lib/jss/webhooks/event_objects/scep_challenge.rb +0 -32
- data/lib/jss/webhooks/event_objects/smart_group.rb +0 -35
- data/lib/jss/webhooks/server_app.rb +0 -37
- data/lib/jss/webhooks/server_app/routes.rb +0 -27
- data/lib/jss/webhooks/server_app/routes/handle_webhook_event.rb +0 -39
- data/lib/jss/webhooks/server_app/routes/home.rb +0 -37
- data/lib/jss/webhooks/server_app/self_signed_cert.rb +0 -65
- data/lib/jss/webhooks/server_app/server.rb +0 -60
- data/lib/jss/webhooks/version.rb +0 -32
data/lib/jss/api_object/user.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
### Copyright 2017 Pixar
|
2
2
|
|
3
|
-
###
|
3
|
+
###
|
4
4
|
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
5
|
### with the following modification; you may not use this file except in
|
6
6
|
### compliance with the Apache License and the following modification to it:
|
7
7
|
### Section 6. Trademarks. is deleted and replaced with:
|
8
|
-
###
|
8
|
+
###
|
9
9
|
### 6. Trademarks. This License does not grant permission to use the trade
|
10
10
|
### names, trademarks, service marks, or product names of the Licensor
|
11
11
|
### and its affiliates, except as required to comply with Section 4(c) of
|
12
12
|
### the License and to reproduce the content of the NOTICE file.
|
13
|
-
###
|
13
|
+
###
|
14
14
|
### You may obtain a copy of the Apache License at
|
15
|
-
###
|
15
|
+
###
|
16
16
|
### http://www.apache.org/licenses/LICENSE-2.0
|
17
|
-
###
|
17
|
+
###
|
18
18
|
### Unless required by applicable law or agreed to in writing, software
|
19
19
|
### distributed under the Apache License with the above modification is
|
20
20
|
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
21
|
### KIND, either express or implied. See the Apache License for the specific
|
22
22
|
### language governing permissions and limitations under the Apache License.
|
23
|
-
###
|
23
|
+
###
|
24
24
|
###
|
25
25
|
|
26
26
|
###
|
@@ -172,7 +172,6 @@ module JSS
|
|
172
172
|
@total_vpp_code_count = @init_data[:links][:total_vpp_code_count]
|
173
173
|
end
|
174
174
|
|
175
|
-
parse_ext_attrs
|
176
175
|
end
|
177
176
|
|
178
177
|
#####################################
|
@@ -0,0 +1,117 @@
|
|
1
|
+
### Copyright 2017 Pixar
|
2
|
+
|
3
|
+
###
|
4
|
+
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
|
+
### with the following modification; you may not use this file except in
|
6
|
+
### compliance with the Apache License and the following modification to it:
|
7
|
+
### Section 6. Trademarks. is deleted and replaced with:
|
8
|
+
###
|
9
|
+
### 6. Trademarks. This License does not grant permission to use the trade
|
10
|
+
### names, trademarks, service marks, or product names of the Licensor
|
11
|
+
### and its affiliates, except as required to comply with Section 4(c) of
|
12
|
+
### the License and to reproduce the content of the NOTICE file.
|
13
|
+
###
|
14
|
+
### You may obtain a copy of the Apache License at
|
15
|
+
###
|
16
|
+
### http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
###
|
18
|
+
### Unless required by applicable law or agreed to in writing, software
|
19
|
+
### distributed under the Apache License with the above modification is
|
20
|
+
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
|
+
### KIND, either express or implied. See the Apache License for the specific
|
22
|
+
### language governing permissions and limitations under the Apache License.
|
23
|
+
###
|
24
|
+
###
|
25
|
+
|
26
|
+
###
|
27
|
+
module JSS
|
28
|
+
|
29
|
+
# A mix-in module to handle VPP-related data in API objects that can be
|
30
|
+
# assigned via VPP.
|
31
|
+
#
|
32
|
+
# To use this module, merely `include VPPable` when defining your
|
33
|
+
# subclass of JSS::APIObject
|
34
|
+
#
|
35
|
+
# classes doing so MUST call {#add_vpp_xml(xmldoc)} in their {#rest_xml} method
|
36
|
+
#
|
37
|
+
module VPPable
|
38
|
+
|
39
|
+
# Mixed-in Constants
|
40
|
+
#####################################
|
41
|
+
VPPABLE = true
|
42
|
+
|
43
|
+
# Mixed-in Attributes
|
44
|
+
#####################################
|
45
|
+
|
46
|
+
# @return [Hash]
|
47
|
+
attr_reader :vpp_codes
|
48
|
+
|
49
|
+
# @return [Integer]
|
50
|
+
attr_reader :vpp_admin_account_id
|
51
|
+
|
52
|
+
# @return [Boolean]
|
53
|
+
attr_reader :assign_vpp_device_based_licenses
|
54
|
+
alias vpp_device_based? assign_vpp_device_based_licenses
|
55
|
+
|
56
|
+
# @return [Integer]
|
57
|
+
attr_reader :total_vpp_licenses
|
58
|
+
alias vpp_total_licenses total_vpp_licenses
|
59
|
+
alias vpp_license_count total_vpp_licenses
|
60
|
+
|
61
|
+
# @return [Integer]
|
62
|
+
attr_reader :remaining_vpp_licenses
|
63
|
+
alias vpp_licenses_remaining remaining_vpp_licenses
|
64
|
+
|
65
|
+
# @return [Integer]
|
66
|
+
attr_reader :used_vpp_licenses
|
67
|
+
alias vpp_licenses_used used_vpp_licenses
|
68
|
+
|
69
|
+
|
70
|
+
# Set whether or not the VPP licenses should be assigned
|
71
|
+
# by device rather than by user
|
72
|
+
#
|
73
|
+
# @param new_val[Boolean] The new value
|
74
|
+
#
|
75
|
+
# @return [void]
|
76
|
+
#
|
77
|
+
def assign_vpp_device_based_licenses=(new_val)
|
78
|
+
return nil if new_val == @assign_vpp_device_based_licenses
|
79
|
+
raise JSS::InvalidDataError, 'New value must be true or false' unless new_val.jss_boolean?
|
80
|
+
@assign_vpp_device_based_licenses = new_val
|
81
|
+
@need_to_update = true
|
82
|
+
end
|
83
|
+
alias vpp_device_based= assign_vpp_device_based_licenses=
|
84
|
+
|
85
|
+
# Mixed-in Private Instance Methods
|
86
|
+
#####################################
|
87
|
+
private
|
88
|
+
|
89
|
+
# Parse the vpp data from the incoming API data
|
90
|
+
#
|
91
|
+
# @return [void]
|
92
|
+
#
|
93
|
+
def parse_vpp
|
94
|
+
@vpp_codes = @init_data[:vpp_codes]
|
95
|
+
@vpp_admin_account_id = @init_data[:vpp][:vpp_admin_account_id]
|
96
|
+
@assign_vpp_device_based_licenses = @init_data[:vpp][:assign_vpp_device_based_licenses]
|
97
|
+
@total_vpp_licenses = @init_data[:vpp][:total_vpp_licenses]
|
98
|
+
@remaining_vpp_licenses = @init_data[:vpp][:remaining_vpp_licenses]
|
99
|
+
@used_vpp_licenses = @init_data[:vpp][:used_vpp_licenses]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Insert an appropriate vpp element into the XML for sending changes
|
103
|
+
# to the JSS
|
104
|
+
#
|
105
|
+
# @param xdoc[REXML::Document] The XML document to work with
|
106
|
+
#
|
107
|
+
# @return [void]
|
108
|
+
#
|
109
|
+
def add_vpp_xml(xdoc)
|
110
|
+
doc_root = xdoc.root
|
111
|
+
vpp = doc_root.add_element 'vpp'
|
112
|
+
vpp.add_element('assign_vpp_device_based_licenses').text = @assign_vpp_device_based_licenses
|
113
|
+
end
|
114
|
+
|
115
|
+
end # VPPable
|
116
|
+
|
117
|
+
end # JSS
|
data/lib/jss/client.rb
CHANGED
@@ -26,40 +26,39 @@
|
|
26
26
|
###
|
27
27
|
module JSS
|
28
28
|
|
29
|
-
|
29
|
+
# Module Variables
|
30
30
|
#####################################
|
31
31
|
|
32
|
-
|
32
|
+
# Module Methods
|
33
33
|
#####################################
|
34
34
|
|
35
|
-
|
35
|
+
# Classes
|
36
36
|
#####################################
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
# This class represents a Casper/JSS Client computer, on which
|
39
|
+
# this code is running.
|
40
|
+
#
|
41
|
+
# Since the class represents the current machine, there's no need
|
42
|
+
# to make an instance of it, all methods are class methods.
|
43
|
+
#
|
44
|
+
# At the moment, only Macintosh computers are supported.
|
45
|
+
#
|
46
|
+
#
|
47
47
|
class Client
|
48
48
|
|
49
|
-
|
50
|
-
### Class Constants
|
49
|
+
# Class Constants
|
51
50
|
#####################################
|
52
51
|
|
53
|
-
|
54
|
-
|
52
|
+
# The Pathname to the jamf binary executable
|
53
|
+
# As of El Capitan (OS X 10.11) the location has moved.
|
55
54
|
ORIG_JAMF_BINARY = Pathname.new '/usr/sbin/jamf'
|
56
55
|
ELCAP_JAMF_BINARY = Pathname.new '/usr/local/jamf/bin/jamf'
|
57
56
|
JAMF_BINARY = ELCAP_JAMF_BINARY.executable? ? ELCAP_JAMF_BINARY : ORIG_JAMF_BINARY
|
58
57
|
|
59
|
-
|
58
|
+
# The Pathname to the jamfHelper executable
|
60
59
|
JAMF_HELPER = Pathname.new '/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper'
|
61
60
|
|
62
|
-
|
61
|
+
# The window_type options for jamfHelper
|
63
62
|
JAMF_HELPER_WINDOW_TYPES = {
|
64
63
|
hud: 'hud',
|
65
64
|
utility: 'utility',
|
@@ -68,28 +67,28 @@ module JSS
|
|
68
67
|
fs: 'fs'
|
69
68
|
}.freeze
|
70
69
|
|
71
|
-
|
70
|
+
# The possible window positions for jamfHelper
|
72
71
|
JAMF_HELPER_WINDOW_POSITIONS = [nil, :ul, :ll, :ur, :lr].freeze
|
73
72
|
|
74
|
-
|
73
|
+
# The available buttons in jamfHelper
|
75
74
|
JAMF_HELPER_BUTTONS = [1, 2].freeze
|
76
75
|
|
77
|
-
|
76
|
+
# The possible alignment positions in jamfHelper
|
78
77
|
JAMF_HELPER_ALIGNMENTS = [:right, :left, :center, :justified, :natural].freeze
|
79
78
|
|
80
|
-
|
79
|
+
# The Pathname to the preferences plist used by the jamf binary
|
81
80
|
JAMF_PLIST = Pathname.new '/Library/Preferences/com.jamfsoftware.jamf.plist'
|
82
81
|
|
83
|
-
|
82
|
+
# The Pathname to the JAMF support folder
|
84
83
|
JAMF_SUPPORT_FOLDER = Pathname.new '/Library/Application Support/JAMF'
|
85
84
|
|
86
|
-
|
85
|
+
# The JAMF receipts folder, where package installs are tracked.
|
87
86
|
RECEIPTS_FOLDER = JAMF_SUPPORT_FOLDER + 'Receipts'
|
88
87
|
|
89
|
-
|
88
|
+
# The JAMF downloads folder
|
90
89
|
DOWNLOADS_FOLDER = JAMF_SUPPORT_FOLDER + 'Downloads'
|
91
90
|
|
92
|
-
|
91
|
+
# These jamf commands don't need root privs (most do)
|
93
92
|
ROOTLESS_JAMF_COMMANDS = [
|
94
93
|
:about,
|
95
94
|
:checkJSSConnection,
|
@@ -101,27 +100,27 @@ module JSS
|
|
101
100
|
].freeze
|
102
101
|
|
103
102
|
#####################################
|
104
|
-
|
103
|
+
# Class Variables
|
105
104
|
#####################################
|
106
105
|
|
107
106
|
#####################################
|
108
|
-
|
107
|
+
# Class Methods
|
109
108
|
#####################################
|
110
109
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
110
|
+
# Get the current IP address as a String.
|
111
|
+
#
|
112
|
+
# This handy code doesn't acutally make a UDP connection,
|
113
|
+
# it just starts to set up the connection, then uses that to get
|
114
|
+
# the local IP.
|
115
|
+
#
|
116
|
+
# Lifted gratefully from
|
117
|
+
# http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/
|
118
|
+
#
|
119
|
+
# @return [String] the current IP address.
|
120
|
+
#
|
122
121
|
def self.my_ip_address
|
123
|
-
|
124
|
-
|
122
|
+
# turn off reverse DNS resolution temporarily
|
123
|
+
# @note the 'socket' library has already been required by 'rest-client'
|
125
124
|
orig = Socket.do_not_reverse_lookup
|
126
125
|
Socket.do_not_reverse_lookup = true
|
127
126
|
|
@@ -133,10 +132,10 @@ module JSS
|
|
133
132
|
Socket.do_not_reverse_lookup = orig
|
134
133
|
end
|
135
134
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
135
|
+
# Who's logged in to the console right now?
|
136
|
+
#
|
137
|
+
# @return [String, nil] the username of the current console user, or nil if none.
|
138
|
+
#
|
140
139
|
def self.console_user
|
141
140
|
cmd = '/usr/sbin/scutil'
|
142
141
|
qry = 'show State:/Users/ConsoleUser'
|
@@ -149,26 +148,26 @@ module JSS
|
|
149
148
|
end # do
|
150
149
|
end
|
151
150
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
151
|
+
# Is the jamf binary installed?
|
152
|
+
#
|
153
|
+
# @return [Boolean] is the jamf binary installed?
|
154
|
+
#
|
156
155
|
def self.installed?
|
157
156
|
JAMF_BINARY.executable?
|
158
157
|
end
|
159
158
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
159
|
+
# What version of the jamf binary is installed?
|
160
|
+
#
|
161
|
+
# @return [String,nil] the version of the jamf binary installed on this client, nil if not installed
|
162
|
+
#
|
164
163
|
def self.jamf_version
|
165
164
|
installed? ? run_jamf(:version).chomp.split('=')[1] : nil
|
166
165
|
end
|
167
166
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
167
|
+
# the URL to the jss for this client
|
168
|
+
#
|
169
|
+
# @return [String] the url to the JSS for this client
|
170
|
+
#
|
172
171
|
def self.jss_url
|
173
172
|
@url = jamf_plist['jss_url']
|
174
173
|
return nil if @url.nil?
|
@@ -179,122 +178,122 @@ module JSS
|
|
179
178
|
@url
|
180
179
|
end
|
181
180
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
181
|
+
# The JSS server hostname for this client
|
182
|
+
#
|
183
|
+
# @return [String] the JSS server for this client
|
184
|
+
#
|
186
185
|
def self.jss_server
|
187
186
|
jss_url
|
188
187
|
@server
|
189
188
|
end
|
190
189
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
190
|
+
# The protocol for JSS connections for this client
|
191
|
+
#
|
192
|
+
# @return [String] the protocol to the JSS for this client, "http" or "https"
|
193
|
+
#
|
195
194
|
def self.jss_protocol
|
196
195
|
jss_url
|
197
196
|
@protocol
|
198
197
|
end
|
199
198
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
199
|
+
# The port number for JSS connections for this client
|
200
|
+
#
|
201
|
+
# @return [Integer] the port to the JSS for this client
|
202
|
+
#
|
204
203
|
def self.jss_port
|
205
204
|
jss_url
|
206
|
-
@port
|
205
|
+
@port
|
207
206
|
end
|
208
207
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
208
|
+
# The contents of the JAMF plist
|
209
|
+
#
|
210
|
+
# @return [Hash] the parsed contents of the JAMF_PLIST if it exists, an empty hash if not
|
211
|
+
#
|
213
212
|
def self.jamf_plist
|
214
213
|
return {} unless JAMF_PLIST.file?
|
215
214
|
Plist.parse_xml `/usr/libexec/PlistBuddy -x -c print #{Shellwords.escape JSS::Client::JAMF_PLIST.to_s}`
|
216
215
|
end
|
217
216
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
217
|
+
# All the JAMF receipts on this client
|
218
|
+
#
|
219
|
+
# @return [Array<Pathname>] an array of Pathnames for all regular files in the jamf receipts folder
|
220
|
+
#
|
222
221
|
def self.receipts
|
223
222
|
raise JSS::NoSuchItemError, "The JAMF Receipts folder doesn't exist on this computer." unless RECEIPTS_FOLDER.exist?
|
224
223
|
RECEIPTS_FOLDER.children.select(&:file?)
|
225
224
|
end
|
226
225
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
226
|
+
# Is the JSS available right now?
|
227
|
+
#
|
228
|
+
# @return [Boolean] is the JSS available now?
|
229
|
+
#
|
231
230
|
def self.jss_available?
|
232
231
|
run_jamf :checkJSSConnection, '-retry 1'
|
233
232
|
$CHILD_STATUS.exitstatus.zero?
|
234
233
|
end
|
235
234
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
235
|
+
# The JSS::Computer object for this computer
|
236
|
+
#
|
237
|
+
# @return [JSS::Computer,nil] The JSS record for this computer, nil if not in the JSS
|
238
|
+
#
|
240
239
|
def self.jss_record
|
241
240
|
JSS::Computer.new udid: udid
|
242
241
|
rescue JSS::NoSuchItemError
|
243
242
|
nil
|
244
243
|
end
|
245
244
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
245
|
+
# The UUID for this computer via system_profiler
|
246
|
+
#
|
247
|
+
# @return [String] the UUID/UDID for this computer
|
248
|
+
#
|
250
249
|
def self.udid
|
251
250
|
hardware_data['platform_UUID']
|
252
251
|
end
|
253
252
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
253
|
+
# The serial number for this computer via system_profiler
|
254
|
+
#
|
255
|
+
# @return [String] the serial number for this computer
|
256
|
+
#
|
258
257
|
def self.serial_number
|
259
258
|
hardware_data['serial_number']
|
260
259
|
end
|
261
260
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
261
|
+
# The parsed HardwareDataType output from system_profiler
|
262
|
+
#
|
263
|
+
# @return [Hash] the HardwareDataType data from the system_profiler command
|
264
|
+
#
|
266
265
|
def self.hardware_data
|
267
266
|
raw = `/usr/sbin/system_profiler SPHardwareDataType -xml 2>/dev/null`
|
268
267
|
Plist.parse_xml(raw)[0]['_items'][0]
|
269
268
|
end
|
270
269
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
270
|
+
# Run an arbitrary jamf binary command.
|
271
|
+
#
|
272
|
+
# @note Most jamf commands require superuser/root privileges.
|
273
|
+
#
|
274
|
+
# @param command[String,Symbol] the jamf binary command to run
|
275
|
+
# The command is the single jamf command that comes after the/usr/bin/jamf.
|
276
|
+
#
|
277
|
+
# @param args[String,Array] the arguments passed to the jamf command.
|
278
|
+
# This is to be passed to Kernel.` (backtick), after being combined with the
|
279
|
+
# jamf binary and the jamf command
|
280
|
+
#
|
281
|
+
# @param verbose[Boolean] Should the stdout & stderr of the jamf binary be sent to
|
282
|
+
# the current stdout in realtime, as well as returned as a string?
|
283
|
+
#
|
284
|
+
# @return [String] the stdout & stderr of the jamf binary.
|
285
|
+
#
|
286
|
+
# @example
|
287
|
+
# These two are equivalent:
|
288
|
+
#
|
289
|
+
# JSS::Client.run_jamf "recon", "-assetTag 12345 -department 'IT Support'"
|
290
|
+
#
|
291
|
+
# JSS::Client.run_jamf :recon, ['-assetTag', '12345', '-department', 'IT Support'"]
|
292
|
+
#
|
293
|
+
#
|
294
|
+
# The details of the Process::Status for the jamf binary process can be captured from $?
|
295
|
+
# immediately after calling. (See Process::Status)
|
296
|
+
#
|
298
297
|
def self.run_jamf(command, args = nil, verbose = false)
|
299
298
|
raise JSS::UnmanagedError, 'The jamf binary is not installed on this computer.' unless installed?
|
300
299
|
raise JSS::UnsupportedError, 'You must have root privileges to run that jamf binary command' unless \
|
@@ -326,102 +325,124 @@ module JSS
|
|
326
325
|
install_out
|
327
326
|
end # run_jamf
|
328
327
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
328
|
+
# A wrapper for the jamfHelper command, which can display a window on the client machine.
|
329
|
+
#
|
330
|
+
# The first parameter must be a symbol defining what kind of window to display. The options are
|
331
|
+
# - :hud - creates an Apple "Heads Up Display" style window
|
332
|
+
# - :utility or :util - creates an Apple "Utility" style window
|
333
|
+
# - :fs or :full_screen or :fullscreen - creates a full screen window that restricts all user input
|
334
|
+
# WARNING: Remote access must be used to unlock machines in this mode
|
335
|
+
#
|
336
|
+
# The remaining options Hash can contain any of the options listed. See below for descriptions.
|
337
|
+
#
|
338
|
+
# The value returned is the Integer exitstatus/stdout (both are the same) of the jamfHelper command.
|
339
|
+
# The meanings of those integers are:
|
340
|
+
#
|
341
|
+
# - 0 - Button 1 was clicked
|
342
|
+
# - 1 - The Jamf Helper was unable to launch
|
343
|
+
# - 2 - Button 2 was clicked
|
344
|
+
# - 3 - Process was started as a launchd task
|
345
|
+
# - XX1 - Button 1 was clicked with a value of XX seconds selected in the drop-down
|
346
|
+
# - XX2 - Button 2 was clicked with a value of XX seconds selected in the drop-down
|
347
|
+
# - 239 - The exit button was clicked
|
348
|
+
# - 240 - The "ProductVersion" in sw_vers did not return 10.5.X, 10.6.X or 10.7.X
|
349
|
+
# - 243 - The window timed-out with no buttons on the screen
|
350
|
+
# - 250 - Bad "-windowType"
|
351
|
+
# - 254 - Cancel button was select with delay option present
|
352
|
+
# - 255 - No "-windowType"
|
353
|
+
#
|
354
|
+
# If the :abandon_process option is given, the integer returned is the Process ID
|
355
|
+
# of the abondoned process running jamfHelper.
|
356
|
+
#
|
357
|
+
# See also /Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -help
|
358
|
+
#
|
359
|
+
# @note the -startlaunchd and -kill options are not available in this implementation, since
|
360
|
+
# they don't work at the moment (casper 9.4).
|
361
|
+
# -startlaunchd seems to be required to NOT use launchd, and when it's ommited, an error is generated
|
362
|
+
# about the launchd plist permissions being incorrect.
|
363
|
+
#
|
364
|
+
# @param window_type[Symbol] The type of window to display
|
365
|
+
#
|
366
|
+
# @param opts[Hash] the options for the window
|
367
|
+
#
|
368
|
+
# @option opts :window_position [Symbol,nil] one of [ nil, :ul, :ll. :ur, :lr ]
|
369
|
+
# Positions window in the upper right, upper left, lower right or lower left of the user's screen
|
370
|
+
# If no input is given, the window defaults to the center of the screen
|
371
|
+
#
|
372
|
+
# @option opts :title [String]
|
373
|
+
# Sets the window's title to the specified string
|
374
|
+
#
|
375
|
+
# @option opts :heading [String]
|
376
|
+
# Sets the heading of the window to the specified string
|
377
|
+
#
|
378
|
+
# @option opts :align_heading [Symbol] one of [:right, :left, :center, :justified, :natural]
|
379
|
+
# Aligns the heading to the specified alignment
|
380
|
+
#
|
381
|
+
# @option opts :description [String]
|
382
|
+
# Sets the main contents of the window to the specified string
|
383
|
+
#
|
384
|
+
# @option opts :align_description [Symbol] one of [:right, :left, :center, :justified, :natural]
|
385
|
+
# Aligns the description to the specified alignment
|
386
|
+
#
|
387
|
+
# @option opts :icon [String,Pathname]
|
388
|
+
# Sets the windows image field to the image located at the specified path
|
389
|
+
#
|
390
|
+
# @option opts :icon_size [Integer]
|
391
|
+
# Changes the image frame to the specified pixel size
|
392
|
+
#
|
393
|
+
# @option opts :full_screen_icon [any value]
|
394
|
+
# Scales the "icon" to the full size of the window.
|
395
|
+
# Note: Only available in full screen mode
|
396
|
+
#
|
397
|
+
# @option opts :button1 [String]
|
398
|
+
# Creates a button with the specified label
|
399
|
+
#
|
400
|
+
# @option opts :button2 [String]
|
401
|
+
# Creates a second button with the specified label
|
402
|
+
#
|
403
|
+
# @option opts :default_button [Integer] either 1 or 2
|
404
|
+
# Sets the default button of the window to the specified button. The Default Button will respond to "return"
|
405
|
+
#
|
406
|
+
# @option opts :cancel_button [Integer] either 1 or 2
|
407
|
+
# Sets the cancel button of the window to the specified button. The Cancel Button will respond to "escape"
|
408
|
+
#
|
409
|
+
# @option opts :timeout [Integer]
|
410
|
+
# Causes the window to timeout after the specified amount of seconds
|
411
|
+
# Note: The timeout will cause the default button, button 1 or button 2 to be selected (in that order)
|
412
|
+
#
|
413
|
+
# @option opts :show_delay_options [String,Array<Integer>] A String of comma-separated Integers, or an Array of Integers.
|
414
|
+
# Enables the "Delay Options Mode". The window will display a dropdown with the values passed through the string
|
415
|
+
#
|
416
|
+
# @option opts :countdown [any value]
|
417
|
+
# Displays a string notifying the user when the window will time out
|
418
|
+
#
|
419
|
+
# @option opts :align_countdown [Symbol] one of [:right, :left, :center, :justified, :natural]
|
420
|
+
# Aligns the countdown to the specified alignment
|
421
|
+
#
|
422
|
+
# @option opts :lock_hud [Boolean]
|
423
|
+
# Removes the ability to exit the HUD by selecting the close button
|
424
|
+
#
|
425
|
+
# @option opts :abandon_process [Boolean] Abandon the jamfHelper process so that your code can exit.
|
426
|
+
# This is mostly used so that a policy can finish while a dialog is waiting
|
427
|
+
# (possibly forever) for user response. When true, the returned value is the
|
428
|
+
# process id of the abandoned jamfHelper process.
|
429
|
+
#
|
430
|
+
# @option opts :output_file [String, Pathname] Save the output of jamfHelper
|
431
|
+
# (the exit code) into this file. This is useful when using abandon_process.
|
432
|
+
# The output file can be examined later to see what happened. If this option
|
433
|
+
# is not provided, no output is saved.
|
434
|
+
#
|
435
|
+
# @option opts :arg_string [String] The jamfHelper commandline args as a single
|
436
|
+
# String, the way you'd specify them in a shell. This is appended to any
|
437
|
+
# Ruby options provided when calling the method. So calling:
|
438
|
+
# JSS::Client.jamf_helper :hud, title: 'This is a title', arg_string: '-heading "this is a heading"'
|
439
|
+
# will run
|
440
|
+
# jamfHelper -windowType hud -title 'this is a title' -heading "this is a heading"
|
441
|
+
# When using this, be careful not to specify the windowType, since it's generated
|
442
|
+
# by the first, required, parameter of this method.
|
443
|
+
#
|
444
|
+
# @return [Integer] the exit status of the jamfHelper command. See above.
|
445
|
+
#
|
425
446
|
def self.jamf_helper(window_type = :hud, opts = {})
|
426
447
|
raise JSS::UnmanagedError, 'The jamfHelper app is not installed properly on this computer.' unless JAMF_HELPER.executable?
|
427
448
|
|
@@ -505,7 +526,7 @@ module JSS
|
|
505
526
|
args << JSS.to_s_and_a(opts[opt])[:arrayform].join(', ')
|
506
527
|
|
507
528
|
when :countdown
|
508
|
-
args << '-countdown'
|
529
|
+
args << '-countdown' if opts[opt]
|
509
530
|
|
510
531
|
when :align_countdown
|
511
532
|
raise JSS::InvalidDataError, ":align_countdown must be one of :#{JAMF_HELPER_ALIGNMENTS.join(', :')}." unless \
|
@@ -514,12 +535,30 @@ module JSS
|
|
514
535
|
args << opts[opt].to_s
|
515
536
|
|
516
537
|
when :lock_hud
|
517
|
-
args << '-lockHUD'
|
538
|
+
args << '-lockHUD' if opts[opt]
|
539
|
+
|
518
540
|
end # case opt
|
519
541
|
end # each do opt
|
520
542
|
|
521
|
-
|
522
|
-
|
543
|
+
cmd = Shellwords.escape JAMF_HELPER.to_s
|
544
|
+
args.each { |arg| cmd << " #{Shellwords.escape arg}" }
|
545
|
+
cmd << " #{opts[:arg_string]}" if opts[:arg_string]
|
546
|
+
cmd << " > #{Shellwords.escape opts[:output_file]}" if opts[:output_file]
|
547
|
+
|
548
|
+
if opts[:abandon_process]
|
549
|
+
pid = Process.fork
|
550
|
+
if pid.nil?
|
551
|
+
# In child
|
552
|
+
exec cmd
|
553
|
+
else
|
554
|
+
# In parent
|
555
|
+
Process.detach(pid)
|
556
|
+
pid
|
557
|
+
end
|
558
|
+
else
|
559
|
+
system cmd
|
560
|
+
$CHILD_STATUS.exitstatus
|
561
|
+
end
|
523
562
|
end # def self.jamf_helper
|
524
563
|
|
525
564
|
end # class Client
|