chook 1.1.2 → 1.1.5b1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +20 -0
- data/README.md +6 -1
- data/bin/chook-server +2 -0
- data/data/com.pixar.chook-server.plist +20 -0
- data/data/sample_handlers/RestAPIOperation.rb +2 -6
- data/lib/chook/event.rb +6 -1
- data/lib/chook/event/handled_event.rb +23 -4
- data/lib/chook/event/handled_event/handlers.rb +149 -49
- data/lib/chook/event/handled_event_logger.rb +1 -1
- data/lib/chook/foundation.rb +1 -0
- data/lib/chook/server.rb +23 -0
- data/lib/chook/server/public/css/chook.css +4 -0
- data/lib/chook/server/public/js/chook.js +8 -29
- data/lib/chook/server/routes.rb +1 -0
- data/lib/chook/server/routes/handle_by_name.rb +65 -0
- data/lib/chook/server/routes/handle_webhook_event.rb +2 -2
- data/lib/chook/server/routes/handlers.rb +6 -4
- data/lib/chook/server/routes/home.rb +16 -1
- data/lib/chook/server/views/handlers.haml +28 -13
- data/lib/chook/server/views/layout.haml +5 -0
- data/lib/chook/server/views/logstream.haml +10 -9
- data/lib/chook/subject.rb +12 -0
- data/lib/chook/subject/dep_device.rb +81 -0
- data/lib/chook/subject/policy_finished.rb +43 -0
- data/lib/chook/version.rb +1 -1
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2a39df5350d3ae528addf0baaebe5a122b1701b08e2e503afd9b0500910120c
|
4
|
+
data.tar.gz: a8a277843eb2606251f8c6000cd25b2e11c60a94c69998046e59f5c0010c4489
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 519c4bf9ab0662a599eeef50e6e6bb637203f22c24a4cdc121bc94f28f239f856d9ff1380422259b67b64cb19554d18e76abb39ceabeb87ea408a9fde6398876
|
7
|
+
data.tar.gz: ad11db916b235f4bc0aaca73aae01b36f38c222555a76004fa4ac7f7e34efa32bc4fb80768366536dfd29a6f56ac5ec0912c6ac7eb1be63e62c7e03cec44170b
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Chook Change Log
|
2
2
|
|
3
|
+
## v 1.1.5 2020-12-11
|
4
|
+
|
5
|
+
- Add support for handling DeviceAddedToDEP webhook events
|
6
|
+
- Updated the handling of ComputerPolicyFinished events to reflect new JSON structure via a PolicyFinished subject class.
|
7
|
+
NOTE: The computer info in the PolicyFinished subject for ComputerPolicyFinished events is located in a hash in the 'computer' attribute of the subject. So to get the SN of the computer that finished a policy, you'd use `event.subject.computer[:serialNumber]`. See the file ..lib/chook/subject/policy_finished.rb.
|
8
|
+
|
9
|
+
### IMPORTANT Note:
|
10
|
+
Version 1.1.5 is probably the last release of v.1x for chook. Version 2 will be a major reworking of the code. While the general principles will remain the same, a lot will be simplified, some will be jettisoned (e.g. the whole TestEvent aspect) and hopefully lots will be optimized to better handle more and faster incoming webhooks. We'll get some test code up to Github asap.
|
11
|
+
|
12
|
+
## v 1.1.4, 2020-08-10
|
13
|
+
|
14
|
+
- Set the server process name to 'chook' - some OS utilities will see it
|
15
|
+
- remove event START messages from info logging, now only visible when log level is debug.
|
16
|
+
- Don't use ruby object IDs as event ids - ruby reuses them.
|
17
|
+
- Server uptime is displayed on the simple admin web UI.
|
18
|
+
|
19
|
+
## v 1.1.3, 2019-10-28
|
20
|
+
|
21
|
+
- Named Handlers! You can create a handler with any file name, and put it in /Library/Application Support/Chook/NamedHandlers then call it specifically from a webhook in Jamf Pro using the url http[s]://your.chook.server.com/handler/handler-filename
|
22
|
+
|
3
23
|
## v 1.1.2, 2019-01-24
|
4
24
|
|
5
25
|
- code cleanup & bugfixes
|
data/README.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
Documentation is a work in progress. Please [get in touch](mailto:chook@pixar.com) for assistance. <3
|
4
4
|
|
5
|
+
### IMPORTANT Note:
|
6
|
+
Version 1.1.5 is probably the last release of v.1x for chook. Version 2 will be a major reworking of the code. While the general principles will remain the same, a lot will be simplified, some will be jettisoned (e.g. the whole TestEvent aspect) and hopefully lots will be optimized to better handle more and faster incoming webhooks. We'll get some test code up to Github asap.
|
7
|
+
|
8
|
+
|
5
9
|
- [Introduction](#introduction)
|
6
10
|
- [Installing Chook](#installing-chook)
|
7
11
|
- [The Server](#the-server)
|
@@ -444,8 +448,9 @@ the `Chook::Subjects` module.
|
|
444
448
|
| Chook::HandledEvents::ComputerAddedEvent | Chook::HandledSubjects::Computer |
|
445
449
|
| Chook::HandledEvents::ComputerCheckInEvent | Chook::HandledSubjects::Computer |
|
446
450
|
| Chook::HandledEvents::ComputerInventoryCompletedEvent | Chook::HandledSubjects::Computer |
|
447
|
-
| Chook::HandledEvents::ComputerPolicyFinishedEvent | Chook::HandledSubjects::
|
451
|
+
| Chook::HandledEvents::ComputerPolicyFinishedEvent | Chook::HandledSubjects::PolicyFinished |
|
448
452
|
| Chook::HandledEvents::ComputerPushCapabilityChangedEvent | Chook::HandledSubjects::Computer |
|
453
|
+
| Chook::HandledEvents::DeviceAddedToDEP | Chook::HandledSubjects::DEPDevice |
|
449
454
|
| Chook::HandledEvents::JSSShutdownEvent | Chook::HandledSubjects::JSS |
|
450
455
|
| Chook::HandledEvents::JSSStartupEvent | Chook::HandledSubjects::JSS |
|
451
456
|
| Chook::HandledEvents::MobileDeviceCheckinEvent | Chook::HandledSubjects::MobileDevice |
|
data/bin/chook-server
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Label</key>
|
6
|
+
<string>com.pixar.chook-server</string>
|
7
|
+
<key>StandardOutPath</key>
|
8
|
+
<string>/var/log/chook-server.log</string>
|
9
|
+
<key>StandardErrorPath</key>
|
10
|
+
<string>/var/log/chook-server.log</string>
|
11
|
+
<key>ProgramArguments</key>
|
12
|
+
<array>
|
13
|
+
<string>/usr/local/pixar/bin/chook-server</string>
|
14
|
+
</array>
|
15
|
+
<key>RunAtLoad</key>
|
16
|
+
<true/>
|
17
|
+
<key>KeepAlive</key>
|
18
|
+
<true/>
|
19
|
+
</dict>
|
20
|
+
</plist>
|
@@ -39,11 +39,7 @@ Chook.event_handler do |event|
|
|
39
39
|
|
40
40
|
action = APIOpHandler::REPORT_ACTIONS[event.subject.restAPIOperationType]
|
41
41
|
|
42
|
-
|
42
|
+
break unless action
|
43
43
|
|
44
|
-
|
45
|
-
The JSS WebHook named '#{event.webhook_name}' was just triggered.
|
46
|
-
It indicates that Casper user '#{event.subject.authorizedUsername}' just used the JSS API to #{action}
|
47
|
-
the JSS #{event.subject.objectTypeName} named '#{event.subject.objectName}' (id #{event.subject.objectID})
|
48
|
-
ENDMSG
|
44
|
+
event.logger.info "API #{action}: #{event.subject.objectTypeName} '#{event.subject.objectName}' (id #{event.subject.objectID})"
|
49
45
|
end
|
data/lib/chook/event.rb
CHANGED
@@ -65,8 +65,9 @@ module Chook
|
|
65
65
|
'ComputerAdded' => Chook::Subject::COMPUTER,
|
66
66
|
'ComputerCheckIn' => Chook::Subject::COMPUTER,
|
67
67
|
'ComputerInventoryCompleted' => Chook::Subject::COMPUTER,
|
68
|
-
'ComputerPolicyFinished' => Chook::Subject::
|
68
|
+
'ComputerPolicyFinished' => Chook::Subject::POLICY_FINISHED,
|
69
69
|
'ComputerPushCapabilityChanged' => Chook::Subject::COMPUTER,
|
70
|
+
'DeviceAddedToDEP' => Chook::Subject::DEP_DEVICE,
|
70
71
|
'JSSShutdown' => Chook::Subject::JAMF_SOFTWARE_SERVER,
|
71
72
|
'JSSStartup' => Chook::Subject::JAMF_SOFTWARE_SERVER,
|
72
73
|
'MobileDeviceCheckIn' => Chook::Subject::MOBILE_DEVICE,
|
@@ -94,6 +95,9 @@ module Chook
|
|
94
95
|
|
95
96
|
#### Attrbutes common to all events
|
96
97
|
|
98
|
+
# @return [String] A unique identifier for this chook event
|
99
|
+
attr_reader :id
|
100
|
+
|
97
101
|
# @return [Integer] The webhook id in the JSS that caused this event
|
98
102
|
attr_reader :webhook_id
|
99
103
|
|
@@ -128,6 +132,7 @@ module Chook
|
|
128
132
|
# event. Any not provided will be nil.
|
129
133
|
#
|
130
134
|
def initialize(**args)
|
135
|
+
@id = "#{Time.now.to_i}-#{SecureRandom.urlsafe_base64 8}"
|
131
136
|
if args[:raw_json]
|
132
137
|
@raw_json = args[:raw_json]
|
133
138
|
@parsed_json = JSON.parse @raw_json, symbolize_names: true
|
@@ -118,10 +118,15 @@ module Chook
|
|
118
118
|
super raw_json: raw_event_json
|
119
119
|
end # init
|
120
120
|
|
121
|
+
def event_class_name
|
122
|
+
self.class.const_get(Chook::Event::EVENT_NAME_CONST)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Run all the general handlers for this event class
|
126
|
+
#
|
121
127
|
def handle
|
122
|
-
|
123
|
-
handlers
|
124
|
-
return 'No handlers loaded' unless handlers.is_a? Array
|
128
|
+
handlers = Handlers.handlers[event_class_name]
|
129
|
+
return "No handlers loaded for #{event_class_name} events" unless handlers.is_a? Array
|
125
130
|
|
126
131
|
handlers.each do |handler|
|
127
132
|
case handler
|
@@ -135,9 +140,23 @@ module Chook
|
|
135
140
|
# the handle method should return a string,
|
136
141
|
# which is the body of the HTTP result for
|
137
142
|
# POSTing the event
|
138
|
-
"Processed by #{handlers.count} handlers"
|
143
|
+
"Processed by #{handlers.count} general handlers"
|
139
144
|
end # def handle
|
140
145
|
|
146
|
+
# run a single handler specified by filename
|
147
|
+
#
|
148
|
+
def handle_by_name(handler_to_run)
|
149
|
+
handler = Handlers.named_handlers[handler_to_run]
|
150
|
+
return "No named handler '#{handler_to_run}'" unless handler
|
151
|
+
|
152
|
+
if handler.is_a? Pathname
|
153
|
+
pipe_to_executable handler
|
154
|
+
else
|
155
|
+
handle_with_proc handler
|
156
|
+
end # if
|
157
|
+
"Processed by named handler '#{handler_to_run}'"
|
158
|
+
end
|
159
|
+
|
141
160
|
# TODO: these threads will die midstream when the server stops.
|
142
161
|
# Find a way to .join them or otherwise clean them up.
|
143
162
|
|
@@ -70,6 +70,11 @@ module Chook
|
|
70
70
|
|
71
71
|
DEFAULT_HANDLER_DIR = '/Library/Application Support/Chook'.freeze
|
72
72
|
|
73
|
+
# Handlers that are only called by name using the route:
|
74
|
+
# post '/handler/:handler_name'
|
75
|
+
# are located in this subdirection of the handler directory
|
76
|
+
NAMED_HANDLER_SUBDIR = 'NamedHandlers'.freeze
|
77
|
+
|
73
78
|
# internal handler files must match this regex somewhere
|
74
79
|
INTERNAL_HANDLER_BLOCK_START_RE = /Chook.event_handler( ?\{| do) *\|/
|
75
80
|
|
@@ -101,12 +106,63 @@ module Chook
|
|
101
106
|
# (The objects also have a #handler_file attribute that is the Pathname)
|
102
107
|
#
|
103
108
|
def self.handlers
|
104
|
-
@handlers
|
109
|
+
@handlers ||= {}
|
110
|
+
end
|
111
|
+
|
112
|
+
# Handlers can check Chook::HandledEvent::Handlers.reloading?
|
113
|
+
# and do stuff if desired.
|
114
|
+
def self.reloading?
|
115
|
+
@reloading
|
116
|
+
end
|
117
|
+
|
118
|
+
# getter for @named_handlers
|
119
|
+
# These handlers are called by name via the route
|
120
|
+
# " post '/handler/:handler_name'"
|
121
|
+
#
|
122
|
+
# They are not tied to any event type by their filenames
|
123
|
+
# its up to the writers of the handlers to make sure
|
124
|
+
# the webhook that calls them is sending the correct event
|
125
|
+
# type.
|
126
|
+
#
|
127
|
+
# The data structure of @named_handlers is a
|
128
|
+
# Hash of Strings to Pathnames or Anon Objects:
|
129
|
+
# {
|
130
|
+
# handler_filename => Pathname or Obj,
|
131
|
+
# handler_filename => Pathname or Obj,
|
132
|
+
# handler_filename => Pathname or Obj
|
133
|
+
# }
|
134
|
+
#
|
135
|
+
# @return [Hash {String => Pathname, Proc}]
|
136
|
+
def self.named_handlers
|
137
|
+
@named_handlers ||= {}
|
138
|
+
end
|
139
|
+
|
140
|
+
# the Pathname objects for all loaded handlers
|
141
|
+
#
|
142
|
+
# @return [Array<Pathname>]
|
143
|
+
#
|
144
|
+
def self.all_handler_paths
|
145
|
+
hndlrs = named_handlers.values
|
146
|
+
hndlrs += handlers.values.flatten
|
147
|
+
hndlrs.map do |hndlr|
|
148
|
+
hndlr.is_a?(Pathname) ? hndlr : hndlr.handler_file
|
149
|
+
end
|
105
150
|
end
|
106
|
-
@handlers ||= {}
|
107
151
|
|
108
152
|
# Load all the event handlers from the handler_dir or an arbitrary dir.
|
109
153
|
#
|
154
|
+
#
|
155
|
+
# Handler files must be either:
|
156
|
+
# - An executable file, which will have the raw JSON from the JSS piped
|
157
|
+
# to it's stdin when executed
|
158
|
+
# or
|
159
|
+
# - A non-executable file of ruby code like this:
|
160
|
+
# Chook.event_handler do |event|
|
161
|
+
# # your code goes here.
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# (see the Chook README for details about writing the ruby handlers)
|
165
|
+
#
|
110
166
|
# @param from_dir [String, Pathname] directory from which to load the
|
111
167
|
# handlers. Defaults to CONFIG.handler_dir or DEFAULT_HANDLER_DIR if
|
112
168
|
# config is unset
|
@@ -120,31 +176,45 @@ module Chook
|
|
120
176
|
# use default if needed
|
121
177
|
from_dir ||= DEFAULT_HANDLER_DIR
|
122
178
|
handler_dir = Pathname.new(from_dir)
|
179
|
+
named_handler_dir = handler_dir + NAMED_HANDLER_SUBDIR
|
123
180
|
load_type = 'Loading'
|
124
181
|
|
125
182
|
if reload
|
183
|
+
@reloading = true
|
126
184
|
@handlers = {}
|
185
|
+
@named_handlers = {}
|
127
186
|
@loaded_handler = nil
|
128
187
|
load_type = 'Re-loading'
|
129
188
|
end
|
130
189
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
190
|
+
# General Handlers
|
191
|
+
Chook.logger.info "#{load_type} general handlers from directory: #{handler_dir}"
|
192
|
+
if handler_dir.directory? && handler_dir.readable?
|
193
|
+
handler_dir.children.each do |handler_file|
|
194
|
+
load_general_handler(handler_file) if handler_file.file? && handler_file.readable?
|
195
|
+
end
|
196
|
+
Chook.logger.info handlers.empty? ? 'No general handlers found' : "Loaded #{handlers.values.flatten.size} general handlers for #{handlers.keys.size} event triggers"
|
197
|
+
else
|
198
|
+
Chook.logger.error "General handler directory '#{from_dir}' not a readable directory. No general handlers loaded. "
|
136
199
|
end
|
137
200
|
|
138
|
-
|
139
|
-
|
201
|
+
# Named Handlers
|
202
|
+
Chook.logger.info "#{load_type} named handlers from directory: #{named_handler_dir}"
|
203
|
+
if named_handler_dir.directory? && named_handler_dir.readable?
|
204
|
+
named_handler_dir.children.each do |handler_file|
|
205
|
+
load_named_handler(handler_file) if handler_file.file? && handler_file.readable?
|
206
|
+
end
|
207
|
+
Chook.logger.info "Loaded #{named_handlers.size} named handlers"
|
208
|
+
else
|
209
|
+
Chook.logger.error "Named handler directory '#{named_handler_dir}' not a readable directory. No named handlers loaded. "
|
140
210
|
end
|
141
211
|
|
142
|
-
|
143
|
-
@loaded_handler = nil
|
212
|
+
@reloading = false
|
144
213
|
end # load handlers
|
145
214
|
|
146
|
-
# Load
|
147
|
-
#
|
215
|
+
# Load a general event handler from a file.
|
216
|
+
#
|
217
|
+
# General Handler files must begin with the name of the event they handle,
|
148
218
|
# e.g. ComputerAdded, followed by: nothing, a dot, a dash, or
|
149
219
|
# and underscore. Case doesn't matter.
|
150
220
|
# So all of these are OK:
|
@@ -154,82 +224,112 @@ module Chook
|
|
154
224
|
# Computeradded-update-ldap
|
155
225
|
# There can be as many as desired for each event.
|
156
226
|
#
|
157
|
-
#
|
158
|
-
# - An executable file, which will have the raw JSON from the JSS piped
|
159
|
-
# to it's stdin when executed
|
160
|
-
# or
|
161
|
-
# - A non-executable file of ruby code like this:
|
162
|
-
# Chook.event_handler do |event|
|
163
|
-
# # your code goes here.
|
164
|
-
# end
|
165
|
-
#
|
166
|
-
# (see the Chook README for details about writing the ruby handlers)
|
167
|
-
#
|
168
|
-
# @param from_file [Pathname] the file from which to load the handler
|
227
|
+
# @param handler_file [Pathname] the file from which to load the handler
|
169
228
|
#
|
170
229
|
# @return [void]
|
171
230
|
#
|
172
|
-
def self.
|
173
|
-
Chook.logger.debug "Starting load of handler file '#{
|
174
|
-
|
231
|
+
def self.load_general_handler(handler_file)
|
232
|
+
Chook.logger.debug "Starting load of general handler file '#{handler_file.basename}'"
|
233
|
+
|
175
234
|
event_name = event_name_from_handler_filename(handler_file)
|
176
235
|
unless event_name
|
177
|
-
Chook.logger.debug "Ignoring file '#{
|
236
|
+
Chook.logger.debug "Ignoring general handler file '#{handler_file.basename}': Filename doesn't start with event name"
|
178
237
|
return
|
179
238
|
end
|
180
239
|
|
181
240
|
# create an array for this event's handlers, if needed
|
182
|
-
|
241
|
+
handlers[event_name] ||= []
|
242
|
+
|
243
|
+
# external? if so, its executable and we only care about its pathname
|
244
|
+
if handler_file.executable?
|
245
|
+
Chook.logger.info "Loading external general handler file '#{handler_file.basename}' for #{event_name} events"
|
246
|
+
handlers[event_name] << handler_file
|
247
|
+
return
|
248
|
+
end
|
249
|
+
|
250
|
+
# Internal, we store an object with a .handle method
|
251
|
+
Chook.logger.info "Loading internal general handler file '#{handler_file.basename}' for #{event_name} events"
|
252
|
+
load_internal_handler handler_file
|
253
|
+
handlers[event_name] << @loaded_handler if @loaded_handler
|
254
|
+
|
255
|
+
end # self.load_general_handler(handler_file)
|
256
|
+
|
257
|
+
# Load a named event handler from a file.
|
258
|
+
#
|
259
|
+
# Named Handler files can have any name, as they are called directly
|
260
|
+
# from a Jamf webhook via URL.
|
261
|
+
#
|
262
|
+
# @param handler_file [Pathname] the file from which to load the handler
|
263
|
+
#
|
264
|
+
# @return [void]
|
265
|
+
#
|
266
|
+
def self.load_named_handler(handler_file)
|
267
|
+
Chook.logger.debug "Starting load of named handler file '#{handler_file.basename}'"
|
183
268
|
|
184
|
-
|
269
|
+
# external? if so, its executable and we only care about its pathname
|
270
|
+
if handler_file.executable?
|
271
|
+
Chook.logger.info "Loading external named handler file '#{handler_file.basename}'"
|
272
|
+
named_handlers[handler_file.basename.to_s] = handler_file
|
273
|
+
return
|
274
|
+
end
|
185
275
|
|
186
|
-
|
187
|
-
|
276
|
+
# Internal, we store an object with a .handle method
|
277
|
+
Chook.logger.info "Loading internal named handler file '#{handler_file.basename}'"
|
278
|
+
load_internal_handler handler_file
|
279
|
+
named_handlers[handler_file.basename.to_s] = @loaded_handler if @loaded_handler
|
280
|
+
end # self.load_general_handler(handler_file)
|
188
281
|
|
189
282
|
# if the given file is executable, store it's path as a handler for the event
|
190
283
|
#
|
284
|
+
# @return [Boolean] did we load an external handler?
|
191
285
|
#
|
192
|
-
def self.load_external_handler(handler_file, event_name)
|
286
|
+
def self.load_external_handler(handler_file, event_name, named)
|
193
287
|
return false unless handler_file.executable?
|
194
288
|
|
195
|
-
|
289
|
+
say_named = named ? 'named ' : ''
|
290
|
+
Chook.logger.info "Loading #{say_named}external handler file '#{handler_file.basename}' for #{event_name} events"
|
291
|
+
|
292
|
+
if named
|
293
|
+
named_handlers[event_name][handler_file.basename.to_s] = handler_file
|
294
|
+
else
|
295
|
+
# store the Pathname, we'll pipe JSON to it
|
296
|
+
handlers[event_name] << handler_file
|
297
|
+
end
|
196
298
|
|
197
|
-
# store the Pathname, we'll pipe JSON to it
|
198
|
-
@handlers[event_name] << handler_file
|
199
299
|
true
|
200
300
|
end
|
201
301
|
|
202
302
|
# if a given path is not executable, try to load it as an internal handler
|
203
303
|
#
|
304
|
+
# @param handler_file[Pathname] the handler file
|
305
|
+
#
|
306
|
+
# @return [Object] and anonymous object that has a .handle method
|
204
307
|
#
|
205
|
-
def self.load_internal_handler(handler_file
|
308
|
+
def self.load_internal_handler(handler_file)
|
206
309
|
# load the file. If written correctly, it will
|
207
310
|
# put an anon. Object with a #handle method into @loaded_handler
|
208
|
-
Chook.logger.info "Loading internal handler file '#{handler_file.basename}' for #{event_name} events"
|
209
|
-
|
210
311
|
unless handler_file.read =~ INTERNAL_HANDLER_BLOCK_START_RE
|
211
|
-
Chook.logger.error "Internal handler file '#{handler_file
|
212
|
-
return
|
312
|
+
Chook.logger.error "Internal handler file '#{handler_file}' missing event_handler block"
|
313
|
+
return nil
|
213
314
|
end
|
214
315
|
|
215
316
|
# reset @loaded_handler - the `load` call will refill it
|
216
317
|
# see Chook.event_handler
|
217
318
|
@loaded_handler = nil
|
319
|
+
|
218
320
|
begin
|
219
321
|
load handler_file.to_s
|
220
322
|
raise '@loaded handler nil after loading file' unless @loaded_handler
|
221
323
|
rescue => e
|
222
|
-
Chook.logger.error "FAILED loading internal handler file '#{handler_file
|
324
|
+
Chook.logger.error "FAILED loading internal handler file '#{handler_file}': #{e}"
|
223
325
|
return
|
224
326
|
end
|
225
327
|
|
226
|
-
# add a method to the object to get its
|
227
|
-
@loaded_handler.define_singleton_method(:handler_file) { handler_file
|
228
|
-
|
229
|
-
@handlers[event_name] << @loaded_handler
|
328
|
+
# add a method to the object to get its Pathname
|
329
|
+
@loaded_handler.define_singleton_method(:handler_file) { handler_file }
|
230
330
|
|
231
|
-
|
232
|
-
@loaded_handler
|
331
|
+
# return it
|
332
|
+
@loaded_handler
|
233
333
|
end
|
234
334
|
|
235
335
|
# Given a handler filename, return the event name it wants to handle
|
data/lib/chook/foundation.rb
CHANGED
data/lib/chook/server.rb
CHANGED
@@ -71,6 +71,7 @@ module Chook
|
|
71
71
|
end # self.run
|
72
72
|
|
73
73
|
def self.prep_to_run
|
74
|
+
@start_time = Time.now
|
74
75
|
log_level ||= Chook.config.log_level
|
75
76
|
@log_level = Chook::Procs::STRING_TO_LOG_LEVEL.call log_level
|
76
77
|
|
@@ -94,6 +95,28 @@ module Chook
|
|
94
95
|
Chook::HandledEvent::Handlers.load_handlers
|
95
96
|
end # prep to run
|
96
97
|
|
98
|
+
def self.starttime
|
99
|
+
@start_time
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.uptime
|
103
|
+
@start_time ? "#{humanize_secs(Time.now - @start_time)} ago" : 'Not Running'
|
104
|
+
end
|
105
|
+
|
106
|
+
# Very handy!
|
107
|
+
# lifted from
|
108
|
+
# http://stackoverflow.com/questions/4136248/how-to-generate-a-human-readable-time-range-using-ruby-on-rails
|
109
|
+
#
|
110
|
+
def self.humanize_secs(secs)
|
111
|
+
[[60, :second], [60, :minute], [24, :hour], [7, :day], [52.179, :week], [1_000_000, :year]].map do |count, name|
|
112
|
+
next unless secs.positive?
|
113
|
+
|
114
|
+
secs, n = secs.divmod(count)
|
115
|
+
n = n.to_i
|
116
|
+
"#{n} #{n == 1 ? name : (name.to_s + 's')}"
|
117
|
+
end.compact.reverse.join(' ')
|
118
|
+
end
|
119
|
+
|
97
120
|
end # class server
|
98
121
|
|
99
122
|
end # module
|
@@ -88,44 +88,23 @@ function hide_handler_viewer() {
|
|
88
88
|
}
|
89
89
|
|
90
90
|
// show the handler editor with the selected handler code
|
91
|
-
// handler = the
|
92
|
-
function
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
// new handler
|
97
|
-
if (handler == 'new_handler') {
|
98
|
-
editing_filename = new_handler_filename();
|
99
|
-
if (editing_filename == 'Name Already Taken') {
|
100
|
-
code = editing_filename;
|
101
|
-
}
|
102
|
-
document.getElementById("handler_viewer").value = code;
|
103
|
-
|
104
|
-
if (document.getElementById("add_handler_external_radio").checked) {
|
105
|
-
type = 'external';
|
106
|
-
} else {
|
107
|
-
type = 'internal';
|
108
|
-
}
|
109
|
-
|
110
|
-
// existing handler
|
111
|
-
} else {
|
112
|
-
fetch_handler_code(handler) ;
|
113
|
-
}
|
114
|
-
var now_editing = editing_filename + ' (' + type + ')'
|
115
|
-
document.getElementById("currently_viewing_filename").innerHTML = now_editing;
|
91
|
+
// handler = the basename of the hander fle.
|
92
|
+
function view_handler_code(handler_path, type) {
|
93
|
+
fetch_handler_code(handler_path) ;
|
94
|
+
document.getElementById("currently_viewing_filename").innerHTML = 'Viewing handler file: ' + handler_path + ' (' + type + ')';
|
116
95
|
document.getElementById("handler_viewer_div").style.display = 'block';
|
117
96
|
}
|
118
97
|
|
119
98
|
// get the code for an existing handler into the editor
|
120
99
|
function fetch_handler_code(handler) {
|
121
|
-
var
|
122
|
-
var url = '/handler_code
|
100
|
+
var viewer = document.getElementById("handler_viewer");
|
101
|
+
var url = '/handler_code?filepath=' + encodeURIComponent(handler)
|
123
102
|
var xhttp = new XMLHttpRequest();
|
124
103
|
xhttp.onreadystatechange = function() {
|
125
104
|
if (this.readyState == 4 && this.status == 200) {
|
126
|
-
|
105
|
+
viewer.value = xhttp.responseText;
|
127
106
|
} else {
|
128
|
-
|
107
|
+
viewer.value = 'ERROR: File Not Found';
|
129
108
|
}
|
130
109
|
};
|
131
110
|
xhttp.open("GET", url, true);
|
data/lib/chook/server/routes.rb
CHANGED
@@ -49,6 +49,7 @@ end # Chook
|
|
49
49
|
|
50
50
|
require 'chook/server/routes/home'
|
51
51
|
require 'chook/server/routes/handle_webhook_event'
|
52
|
+
require 'chook/server/routes/handle_by_name'
|
52
53
|
require 'chook/server/routes/handlers'
|
53
54
|
require 'chook/server/routes/login_logout'
|
54
55
|
require 'chook/server/routes/log'
|
@@ -0,0 +1,65 @@
|
|
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
|
+
module Chook
|
27
|
+
|
28
|
+
# see server.rb
|
29
|
+
class Server < Sinatra::Base
|
30
|
+
|
31
|
+
post '/handler/:handler_name' do
|
32
|
+
# enforce http basic auth if needed
|
33
|
+
protect_via_basic_auth!
|
34
|
+
|
35
|
+
# rewind to ensure read-pointer is at the start
|
36
|
+
request.body.rewind #
|
37
|
+
raw_json = request.body.read
|
38
|
+
|
39
|
+
event = Chook::HandledEvent.parse_event raw_json
|
40
|
+
|
41
|
+
if event.nil?
|
42
|
+
logger.error "Empty JSON from #{request.ip}"
|
43
|
+
result = 400
|
44
|
+
else
|
45
|
+
|
46
|
+
event.logger.debug "START From #{request.ip}, WebHook '#{event.webhook_name}' (id: #{event.webhook_id})"
|
47
|
+
event.logger.debug "Thread id: #{Thread.current.object_id}; JSON: #{raw_json}"
|
48
|
+
|
49
|
+
result = event.handle_by_name params[:handler_name]
|
50
|
+
|
51
|
+
event.logger.debug "END #{result}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# this route shouldn't have a session expiration
|
55
|
+
# And when it does, the date format is wrong, and the
|
56
|
+
# JAMFSoftwareServerLog complains about it for every
|
57
|
+
# webhook sent.
|
58
|
+
env['rack.session.options'].delete :expire_after
|
59
|
+
|
60
|
+
result
|
61
|
+
end # post
|
62
|
+
|
63
|
+
end # class
|
64
|
+
|
65
|
+
end # module
|
@@ -42,12 +42,12 @@ module Chook
|
|
42
42
|
result = 400
|
43
43
|
else
|
44
44
|
|
45
|
-
event.logger.
|
45
|
+
event.logger.debug "START From #{request.ip}, WebHook '#{event.webhook_name}' (id: #{event.webhook_id})"
|
46
46
|
event.logger.debug "Thread id: #{Thread.current.object_id}; JSON: #{raw_json}"
|
47
47
|
|
48
48
|
result = event.handle
|
49
49
|
|
50
|
-
event.logger.
|
50
|
+
event.logger.debug "END #{result}"
|
51
51
|
end
|
52
52
|
|
53
53
|
# this route shouldn't have a session expiration
|
@@ -35,10 +35,12 @@ module Chook
|
|
35
35
|
'Handlers reloaded'
|
36
36
|
end # get /
|
37
37
|
|
38
|
-
# used by javascript to fetch the content of a handler
|
39
|
-
get '/handler_code
|
40
|
-
file =
|
41
|
-
|
38
|
+
# used by javascript to fetch the content of a handler file
|
39
|
+
get '/handler_code' do
|
40
|
+
file = Pathname.new params[:filepath]
|
41
|
+
|
42
|
+
# only if its a known handler path
|
43
|
+
if Chook::HandledEvent::Handlers.all_handler_paths.include?(file) && file.file?
|
42
44
|
body file.read
|
43
45
|
else
|
44
46
|
404
|
@@ -39,13 +39,28 @@ module Chook
|
|
39
39
|
file = handler
|
40
40
|
type = :external
|
41
41
|
else
|
42
|
-
file =
|
42
|
+
file = handler.handler_file
|
43
43
|
type = :internal
|
44
44
|
end # if else
|
45
45
|
@handlers_for_admin_page << { event: eventname, file: file, type: type }
|
46
46
|
end # handlers each
|
47
47
|
end # Handlers.handlers.each
|
48
48
|
|
49
|
+
# a list of current named handlers for the admin page
|
50
|
+
@named_handlers_for_admin_page = []
|
51
|
+
|
52
|
+
Chook::HandledEvent::Handlers.named_handlers.each do |name, handler|
|
53
|
+
if handler.is_a? Pathname
|
54
|
+
file = handler
|
55
|
+
type = :external
|
56
|
+
else
|
57
|
+
file = handler.handler_file
|
58
|
+
type = :internal
|
59
|
+
end # if else
|
60
|
+
@named_handlers_for_admin_page << { file: file, type: type }
|
61
|
+
end # handlers each
|
62
|
+
|
63
|
+
|
49
64
|
# the current config, for the admin page
|
50
65
|
@config_text =
|
51
66
|
if Chook::Configuration::DEFAULT_CONF_FILE.file?
|
@@ -5,33 +5,49 @@
|
|
5
5
|
Hide
|
6
6
|
|
7
7
|
|
8
|
-
Current Webhook Handlers (#{@handlers_for_admin_page.size})
|
9
|
-
|
10
|
-
#handlers_div
|
11
|
-
|
12
|
-
Handler Directory:
|
13
|
-
%span.monospaced= Chook.config.handler_dir.to_s
|
14
|
-
|
8
|
+
Current Webhook Handlers (#{@handlers_for_admin_page.size + @named_handlers_for_admin_page.size})
|
15
9
|
|
16
10
|
%button#reload_all_handlers_btn{ type: 'button', onClick: 'reload_handlers();', title: 'reload all handlers' }
|
17
|
-
Reload
|
11
|
+
Reload All
|
18
12
|
|
19
13
|
%span#reloaded_notification
|
20
14
|
|
15
|
+
#handlers_div
|
16
|
+
General Handler Directory:
|
17
|
+
%span.monospaced= Chook.config.handler_dir.to_s
|
18
|
+
|
19
|
+
|
21
20
|
%table#handlers_table
|
22
21
|
%tr#handlers_table_header_row
|
23
|
-
%th.handlers_table_cell Event
|
24
|
-
%th.handlers_table_cell{ width: '10%' } Handler Type
|
25
22
|
%th.handlers_table_cell File Name
|
23
|
+
%th.handlers_table_cell{ width: '10%' } Handler Type
|
26
24
|
%th.handlers_table_cell Actions
|
27
25
|
|
28
26
|
- @handlers_for_admin_page.each do |hndlr_info|
|
29
27
|
%tr
|
30
|
-
%td.handlers_table_cell= hndlr_info[:
|
28
|
+
%td.handlers_table_cell= hndlr_info[:file].basename.to_s
|
31
29
|
%td.handlers_table_cell= hndlr_info[:type].to_s
|
30
|
+
%td.handlers_table_cell
|
31
|
+
%button.edit_handler_btn{ type: 'button', onClick: "view_handler_code('#{hndlr_info[:file]}', '#{hndlr_info[:type]}');", title: 'View this handler' }
|
32
|
+
View
|
33
|
+
%br
|
34
|
+
%br
|
35
|
+
Named Handler Directory:
|
36
|
+
%span.monospaced= Chook.config.handler_dir.to_s + "/#{Chook::HandledEvent::Handlers::NAMED_HANDLER_SUBDIR}"
|
37
|
+
|
38
|
+
|
39
|
+
%table#handlers_table
|
40
|
+
%tr#handlers_table_header_row
|
41
|
+
%th.handlers_table_cell File Name
|
42
|
+
%th.handlers_table_cell{ width: '10%' } Handler Type
|
43
|
+
%th.handlers_table_cell Actions
|
44
|
+
|
45
|
+
- @named_handlers_for_admin_page.each do |hndlr_info|
|
46
|
+
%tr
|
32
47
|
%td.handlers_table_cell= hndlr_info[:file].basename.to_s
|
48
|
+
%td.handlers_table_cell= hndlr_info[:type].to_s
|
33
49
|
%td.handlers_table_cell
|
34
|
-
%button.edit_handler_btn{ type: 'button', onClick: "
|
50
|
+
%button.edit_handler_btn{ type: 'button', onClick: "view_handler_code('#{hndlr_info[:file]}', '#{hndlr_info[:type]}');", title: 'View this handler' }
|
35
51
|
View
|
36
52
|
|
37
53
|
#handler_viewer_div
|
@@ -41,7 +57,6 @@
|
|
41
57
|
%button#hide_handler_viewer_btn{ type: 'button', onClick: 'hide_handler_viewer();', title: 'hide the handler editor' }
|
42
58
|
Hide
|
43
59
|
|
44
|
-
Viewing handler:
|
45
60
|
%span.monospaced#currently_viewing_filename -nothing-
|
46
61
|
|
47
62
|
|
@@ -34,6 +34,11 @@
|
|
34
34
|
%span.def_dialect Australian/NZ informal
|
35
35
|
%br/
|
36
36
|
%span.def_definition a chicken or fowl
|
37
|
+
%td#serverstats{ valign: 'bottom' }
|
38
|
+
Server started: #{Chook::Server.starttime.strftime '%Y-%m-%d %H:%M:%S'}
|
39
|
+
%br/
|
40
|
+
(#{Chook::Server.uptime})
|
41
|
+
|
37
42
|
%hr/
|
38
43
|
- if Chook.config.admin_user
|
39
44
|
#login_logout_div
|
@@ -5,8 +5,17 @@
|
|
5
5
|
Hide
|
6
6
|
|
7
7
|
|
8
|
-
The Live Chook Log
|
8
|
+
The Live Chook Log
|
9
9
|
|
10
|
+
Server Log Level:
|
11
|
+
%select#log_level_select{ onchange: 'change_log_level();',
|
12
|
+
title: 'changes here affect logging the server, not just your view' }
|
13
|
+
|
14
|
+
%option{ value: 'fatal', selected: Chook.logger.level == Logger::FATAL } fatal
|
15
|
+
%option{ value: 'error', selected: Chook.logger.level == Logger::ERROR } error
|
16
|
+
%option{ value: 'warn', selected: Chook.logger.level == Logger::WARN } warn
|
17
|
+
%option{ value: 'info', selected: Chook.logger.level == Logger::INFO } info
|
18
|
+
%option{ value: 'debug', selected: Chook.logger.level == Logger::DEBUG } debug
|
10
19
|
|
11
20
|
#logbox_div
|
12
21
|
#logbox_btns
|
@@ -19,14 +28,6 @@
|
|
19
28
|
|
20
29
|
|
21
30
|
|
22
|
-
Server Log Level:
|
23
|
-
%select#log_level_select{ onchange: 'change_log_level();',
|
24
|
-
title: 'changes here affect logging the server, not just your view' }
|
25
31
|
|
26
|
-
%option{ value: 'fatal', selected: Chook.logger.level == Logger::FATAL } fatal
|
27
|
-
%option{ value: 'error', selected: Chook.logger.level == Logger::ERROR } error
|
28
|
-
%option{ value: 'warn', selected: Chook.logger.level == Logger::WARN } warn
|
29
|
-
%option{ value: 'info', selected: Chook.logger.level == Logger::INFO } info
|
30
|
-
%option{ value: 'debug', selected: Chook.logger.level == Logger::DEBUG } debug
|
31
32
|
|
32
33
|
%textarea.monospaced#logbox{ readonly: true, rows: 20 }
|
data/lib/chook/subject.rb
CHANGED
@@ -49,6 +49,11 @@ module Chook
|
|
49
49
|
# Chook::HandledSubjects and Chook::TestSubjects
|
50
50
|
COMPUTER = 'Computer'.freeze
|
51
51
|
|
52
|
+
# The name of the DeviceAddedtoDEP subject (a.k.a. 'event_object')
|
53
|
+
# as known to the JSS. Also the class name of such subjects in
|
54
|
+
# Chook::HandledSubjects and Chook::TestSubjects
|
55
|
+
DEP_DEVICE = 'DEPDevice'.freeze
|
56
|
+
|
52
57
|
# The name of the JSS subject (a.k.a. 'event_object')
|
53
58
|
# as known to the JSS. Also the class name of such subjects in
|
54
59
|
# Chook::HandledSubjects and Chook::TestSubjects
|
@@ -64,6 +69,11 @@ module Chook
|
|
64
69
|
# Chook::HandledSubjects and Chook::TestSubjects
|
65
70
|
PATCH_SW_UPDATE = 'PatchSoftwareTitleUpdated'.freeze
|
66
71
|
|
72
|
+
# The name of the ComputerPolicyFinished subject (a.k.a. 'event_object')
|
73
|
+
# as known to the JSS. Also the class name of such subjects in
|
74
|
+
# Chook::HandledSubjects and Chook::TestSubjects
|
75
|
+
POLICY_FINISHED = 'PolicyFinished'.freeze
|
76
|
+
|
67
77
|
# The name of the Push subject (a.k.a. 'event_object')
|
68
78
|
# as known to the JSS. Also the class name of such subjects in
|
69
79
|
# Chook::HandledSubjects and Chook::TestSubjects
|
@@ -140,3 +150,5 @@ require 'chook/subject/rest_api_operation'
|
|
140
150
|
require 'chook/subject/scep_challenge'
|
141
151
|
require 'chook/subject/smart_group'
|
142
152
|
require 'chook/test_subjects'
|
153
|
+
require 'chook/subject/dep_device'
|
154
|
+
require 'chook/subject/policy_finished'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
### Copyright 2020 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
|
+
Chook::Subject.classes[Chook::Subject::DEP_DEVICE] = {
|
26
|
+
assetTag: {
|
27
|
+
validation: String,
|
28
|
+
# randomizer: ,
|
29
|
+
# sampler: ,
|
30
|
+
# api_object_attribute:
|
31
|
+
},
|
32
|
+
description: {
|
33
|
+
validation: String,
|
34
|
+
randomizer: :word,
|
35
|
+
# sampler: ,
|
36
|
+
# api_object_attribute:
|
37
|
+
},
|
38
|
+
deviceAssignedDate: {
|
39
|
+
to_json: :to_jss_epoch,
|
40
|
+
validation: Time,
|
41
|
+
randomizer: :time,
|
42
|
+
# sampler: ,
|
43
|
+
# api_object_attribute:
|
44
|
+
},
|
45
|
+
deviceEnrollmentProgramInstanceId: {
|
46
|
+
validation: Integer,
|
47
|
+
randomizer: :int,
|
48
|
+
# sampler: ,
|
49
|
+
# api_object_attribute:
|
50
|
+
},
|
51
|
+
model: {
|
52
|
+
validation: String,
|
53
|
+
randomizer: [:computer_model, :mobile_model], # /:
|
54
|
+
# sampler: ,
|
55
|
+
api_object_attribute: [:hardware, :model]
|
56
|
+
},
|
57
|
+
serialNumber: {
|
58
|
+
validation: String, #:validate_serial_number,
|
59
|
+
# randomizer: :computer_serial_number,
|
60
|
+
# sampler: ,
|
61
|
+
api_object_attribute: :serial_number
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
# https://www.jamf.com/developers/webhooks/#deviceaddedtoDEP
|
66
|
+
# {
|
67
|
+
# "event": {
|
68
|
+
# "assetTag": "1664194",
|
69
|
+
# "description": "Mac Pro",
|
70
|
+
# "deviceAssignedDate": 1552478234000,
|
71
|
+
# "deviceEnrollmentProgramInstanceId": 1,
|
72
|
+
# "model": "Mac Pro",
|
73
|
+
# "serialNumber": "92D8014694C4BE96B3"
|
74
|
+
# },
|
75
|
+
# "webhook": {
|
76
|
+
# "eventTimestamp": 1553550275590,
|
77
|
+
# "id": 1,
|
78
|
+
# "name": "Webhook Documentation",
|
79
|
+
# "webhookEvent": "DeviceAddedToDEP"
|
80
|
+
# }
|
81
|
+
# }
|
@@ -0,0 +1,43 @@
|
|
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
|
+
# Add the attrbutes of a Computer subject to the Chook::Subject.attributes
|
27
|
+
# hash, to be used in defining Chook::TestSubjects::Computer and
|
28
|
+
# Chook::HandledSubjects::Computer
|
29
|
+
#
|
30
|
+
Chook::Subject.classes[Chook::Subject::POLICY_FINISHED] = {
|
31
|
+
computer: {
|
32
|
+
validation: Hash,
|
33
|
+
api_object_attribute: :computer
|
34
|
+
},
|
35
|
+
policyId: {
|
36
|
+
validation: Integer,
|
37
|
+
api_object_attribute: :policyId
|
38
|
+
},
|
39
|
+
successful: {
|
40
|
+
validation: :boolean,
|
41
|
+
api_object_attribute: :successful
|
42
|
+
}
|
43
|
+
}
|
data/lib/chook/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.5b1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Lasell
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-12-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- README.md
|
88
88
|
- bin/chook-server
|
89
89
|
- data/chook.conf.example
|
90
|
+
- data/com.pixar.chook-server.plist
|
90
91
|
- data/sample_handlers/RestAPIOperation-executable
|
91
92
|
- data/sample_handlers/RestAPIOperation.rb
|
92
93
|
- data/sample_handlers/SmartGroupComputerMembershipChange-executable
|
@@ -131,6 +132,7 @@ files:
|
|
131
132
|
- lib/chook/server/public/js/chook.js
|
132
133
|
- lib/chook/server/public/js/logstream.js
|
133
134
|
- lib/chook/server/routes.rb
|
135
|
+
- lib/chook/server/routes/handle_by_name.rb
|
134
136
|
- lib/chook/server/routes/handle_webhook_event.rb
|
135
137
|
- lib/chook/server/routes/handlers.rb
|
136
138
|
- lib/chook/server/routes/home.rb
|
@@ -145,10 +147,12 @@ files:
|
|
145
147
|
- lib/chook/server/views/sketch_admin
|
146
148
|
- lib/chook/subject.rb
|
147
149
|
- lib/chook/subject/computer.rb
|
150
|
+
- lib/chook/subject/dep_device.rb
|
148
151
|
- lib/chook/subject/handled_subject.rb
|
149
152
|
- lib/chook/subject/jss.rb
|
150
153
|
- lib/chook/subject/mobile_device.rb
|
151
154
|
- lib/chook/subject/patch_software_title_update.rb
|
155
|
+
- lib/chook/subject/policy_finished.rb
|
152
156
|
- lib/chook/subject/push.rb
|
153
157
|
- lib/chook/subject/randomizers.rb
|
154
158
|
- lib/chook/subject/rest_api_operation.rb
|
@@ -175,12 +179,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
175
179
|
version: '0'
|
176
180
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
181
|
requirements:
|
178
|
-
- - "
|
182
|
+
- - ">"
|
179
183
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
184
|
+
version: 1.3.1
|
181
185
|
requirements: []
|
182
|
-
|
183
|
-
rubygems_version: 2.7.8
|
186
|
+
rubygems_version: 3.0.3
|
184
187
|
signing_key:
|
185
188
|
specification_version: 4
|
186
189
|
summary: A Ruby framework for simulating and processing Jamf Pro Webhook Events
|