chook 1.0.1.b2 → 1.1.5

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.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +56 -0
  3. data/README.md +363 -127
  4. data/bin/chook-server +31 -1
  5. data/data/chook.conf.example +183 -0
  6. data/data/com.pixar.chook-server.plist +20 -0
  7. data/data/sample_handlers/RestAPIOperation.rb +11 -11
  8. data/data/sample_handlers/SmartGroupComputerMembershipChange.rb +3 -6
  9. data/data/sample_jsons/SmartGroupComputerMembershipChange.json +3 -1
  10. data/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +3 -1
  11. data/lib/chook/configuration.rb +27 -8
  12. data/lib/chook/event.rb +6 -1
  13. data/lib/chook/event/handled_event.rb +36 -9
  14. data/lib/chook/event/handled_event/handlers.rb +260 -98
  15. data/lib/chook/event/handled_event_logger.rb +86 -0
  16. data/lib/chook/event_handling.rb +1 -0
  17. data/lib/chook/foundation.rb +3 -0
  18. data/lib/chook/procs.rb +17 -1
  19. data/lib/chook/server.rb +73 -72
  20. data/lib/chook/server/auth.rb +164 -0
  21. data/lib/chook/server/log.rb +215 -0
  22. data/lib/chook/server/public/css/chook.css +133 -0
  23. data/lib/chook/server/public/imgs/ChookLogoAlMcWhiggin.png +0 -0
  24. data/lib/chook/server/public/js/chook.js +126 -0
  25. data/lib/chook/server/public/js/logstream.js +101 -0
  26. data/lib/chook/server/routes.rb +28 -0
  27. data/lib/chook/server/routes/handle_by_name.rb +65 -0
  28. data/lib/chook/server/routes/handle_webhook_event.rb +27 -3
  29. data/lib/chook/server/routes/handlers.rb +52 -0
  30. data/lib/chook/server/routes/home.rb +48 -1
  31. data/lib/chook/server/routes/log.rb +105 -0
  32. data/lib/chook/server/routes/login_logout.rb +48 -0
  33. data/lib/chook/server/views/admin.haml +11 -0
  34. data/lib/chook/server/views/bak.haml +48 -0
  35. data/lib/chook/server/views/config.haml +15 -0
  36. data/lib/chook/server/views/handlers.haml +63 -0
  37. data/lib/chook/server/views/layout.haml +64 -0
  38. data/lib/chook/server/views/logstream.haml +33 -0
  39. data/lib/chook/server/views/sketch_admin +44 -0
  40. data/lib/chook/subject.rb +13 -2
  41. data/lib/chook/subject/dep_device.rb +81 -0
  42. data/lib/chook/subject/policy_finished.rb +43 -0
  43. data/lib/chook/subject/smart_group.rb +6 -0
  44. data/lib/chook/version.rb +1 -1
  45. metadata +79 -19
@@ -0,0 +1,133 @@
1
+ @charset "UTF-8";
2
+
3
+ /* ******* General Styling ******* */
4
+
5
+ .monospaced {
6
+ font-family: "Lucida Console", Monaco, monospace;
7
+ }
8
+
9
+
10
+ /* ******* Title Header Area ******* */
11
+
12
+ .chook_title {
13
+ font-weight: bold;
14
+ font-size: 2.5em;
15
+ }
16
+
17
+ #header_version {
18
+ font-size: 0.5em;
19
+ }
20
+
21
+ #definition {
22
+ line-height: 1.6;
23
+ }
24
+
25
+ #serverstats {
26
+ vertical-align: bottom;
27
+ }
28
+
29
+ .def_pronunciation {
30
+ font-style: italic;
31
+ font-size: 1.2em;
32
+ }
33
+
34
+ .def_part_of_speech {
35
+ font-weight: bold;
36
+ }
37
+
38
+ .def_dialect {
39
+ font-style: italic;
40
+ }
41
+
42
+ .def_definition {
43
+ font-size: 1.2em;
44
+ }
45
+
46
+ #login_incorrect {
47
+ color: red;
48
+ }
49
+
50
+ /* ******* Section Label Areas ******* */
51
+
52
+ .section_label {
53
+ padding-bottom: 5px;
54
+ }
55
+
56
+ /* ******* Live Log Section ******* */
57
+
58
+ #hide_log_btn {
59
+ display: none;
60
+ }
61
+
62
+ #logbox_div {
63
+ display: none;
64
+ }
65
+
66
+ #logbox_btns {
67
+ padding-bottom: 5px;
68
+ }
69
+
70
+ #logbox {
71
+ width: 100%;
72
+ }
73
+
74
+ /* ******* Handlers Section ******* */
75
+
76
+ #hide_handlers_btn {
77
+ display: none;
78
+ }
79
+
80
+ #handlers_div {
81
+ display: none;
82
+ }
83
+
84
+ #handlers_table {
85
+ width: 100%;
86
+ border: 1px solid black;
87
+ border-collapse: collapse;
88
+ margin-top: 5px;
89
+ padding-bottom: 5px;
90
+ }
91
+
92
+ #handlers_table_header_row {
93
+ text-align: left;
94
+ border: 1px solid black;
95
+ border-collapse: collapse;
96
+ background-color: LightGrey;
97
+ padding-top: 4px;
98
+ padding-left: 3px;
99
+ }
100
+
101
+ .handlers_table_cell {
102
+ text-align: left;
103
+ border: 1px solid black;
104
+ border-collapse: collapse;
105
+ padding-top: 4px;
106
+ padding-left: 3px;
107
+ }
108
+
109
+ #handler_viewer_div {
110
+ display: none;
111
+ padding-top: 15px;
112
+ }
113
+
114
+ #handler_viewer {
115
+ width: 95%;
116
+ border: 3px solid black;
117
+ padding-top: 5px;
118
+ }
119
+
120
+ /* ******* Handlers Section ******* */
121
+
122
+ #hide_config_btn {
123
+ display: none;
124
+ }
125
+
126
+ #config_div {
127
+ display: none;
128
+ }
129
+
130
+ #config_viewer_div {
131
+ margin-top: 5px;
132
+ padding-bottom: 5px;
133
+ }
@@ -0,0 +1,126 @@
1
+ // log out of basic auth by sending an incorrect name /pw
2
+ // may not work on all browsers
3
+ // see second comment at
4
+ // https://stackoverflow.com/questions/233507/how-to-log-out-user-from-web-site-using-basic-authentication#492926
5
+
6
+ function logout() {
7
+ //var logged_out_page = window.location.protocol + '//xxxx:xxxx@' + window.location.host + '/login';
8
+
9
+ var xhttp = new XMLHttpRequest();
10
+
11
+ xhttp.onreadystatechange = function() {
12
+ if (this.readyState == 4) {
13
+ window.location = "/login";
14
+ }
15
+ };
16
+
17
+ xhttp.open("GET", "/LOG_OUT:no_such_pw@logout", true);
18
+ xhttp.setRequestHeader("Authorization", "Basic " + btoa("LOG_OUT:no_such_pw"));
19
+ xhttp.send();
20
+ }
21
+
22
+ // show the logbox
23
+ function view_log() {
24
+ document.getElementById("pause_log").checked = false
25
+ document.getElementById("logbox_div").style.display = 'block';
26
+ document.getElementById("view_log_btn").style.display = 'none';
27
+ document.getElementById("hide_log_btn").style.display = 'inline';
28
+ start_log_stream();
29
+ update_logbox();
30
+ }
31
+
32
+ // hide the logbox
33
+ function hide_log() {
34
+ document.getElementById("logbox_div").style.display = 'none';
35
+ document.getElementById("view_log_btn").style.display = 'inline';
36
+ document.getElementById("hide_log_btn").style.display = 'none';
37
+ document.getElementById("pause_log").checked = true;
38
+ }
39
+
40
+ // clear the log stream
41
+ function clear_log(){
42
+ document.getElementById("logbox").value = '';
43
+ log_source = '';
44
+ }
45
+
46
+ // change the log level
47
+ function change_log_level() {
48
+ var new_level = document.getElementById("log_level_select").value
49
+ var url = "/set_log_level/" + new_level
50
+ var xhttp = new XMLHttpRequest();
51
+ xhttp.open("PUT", url, true);
52
+ xhttp.send();
53
+ }
54
+
55
+ // reload the handlers
56
+ function reload_handlers() {
57
+ var url = '/reload_handlers';
58
+ var xhttp = new XMLHttpRequest();
59
+ xhttp.onreadystatechange = function() {
60
+ if (this.readyState == 4 && this.status == 200) {
61
+ now = new Date().toLocaleString();
62
+ document.getElementById("reloaded_notification").innerHTML = 'Reloaded at ' + now;
63
+ } else {
64
+ document.getElementById("reloaded_notification").innerHTML = 'Reload Failed.';
65
+ }
66
+ };
67
+ xhttp.open("GET", url, true);
68
+ xhttp.send();
69
+ }
70
+
71
+ // show the handler area
72
+ function view_handlers() {
73
+ document.getElementById("handlers_div").style.display = 'block';
74
+ document.getElementById("view_handlers_btn").style.display = 'none';
75
+ document.getElementById("hide_handlers_btn").style.display = 'inline';
76
+ }
77
+
78
+ // hide the handler area
79
+ function hide_handlers() {
80
+ document.getElementById("handlers_div").style.display = 'none';
81
+ document.getElementById("view_handlers_btn").style.display = 'inline';
82
+ document.getElementById("hide_handlers_btn").style.display = 'none';
83
+ }
84
+
85
+ // hide the handler editor
86
+ function hide_handler_viewer() {
87
+ document.getElementById("handler_viewer_div").style.display = 'none';
88
+ }
89
+
90
+ // show the handler editor with the selected handler code
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 + ')';
95
+ document.getElementById("handler_viewer_div").style.display = 'block';
96
+ }
97
+
98
+ // get the code for an existing handler into the editor
99
+ function fetch_handler_code(handler) {
100
+ var viewer = document.getElementById("handler_viewer");
101
+ var url = '/handler_code?filepath=' + encodeURIComponent(handler)
102
+ var xhttp = new XMLHttpRequest();
103
+ xhttp.onreadystatechange = function() {
104
+ if (this.readyState == 4 && this.status == 200) {
105
+ viewer.value = xhttp.responseText;
106
+ } else {
107
+ viewer.value = 'ERROR: File Not Found';
108
+ }
109
+ };
110
+ xhttp.open("GET", url, true);
111
+ xhttp.send();
112
+ }
113
+
114
+ // show the config area
115
+ function view_config() {
116
+ document.getElementById("config_div").style.display = 'block';
117
+ document.getElementById("view_config_btn").style.display = 'none';
118
+ document.getElementById("hide_config_btn").style.display = 'inline';
119
+ }
120
+
121
+ // hide the config area
122
+ function hide_config() {
123
+ document.getElementById("config_div").style.display = 'none';
124
+ document.getElementById("view_config_btn").style.display = 'inline';
125
+ document.getElementById("hide_config_btn").style.display = 'none';
126
+ }
@@ -0,0 +1,101 @@
1
+
2
+ // Vars
3
+ //////////////////////////////////
4
+
5
+ // the url that will provide the stream
6
+ var log_stream_url = '/subscribe_to_log_stream';
7
+
8
+ // the EventSource that will get events from the url
9
+ var log_source
10
+
11
+ // the log box on the info page
12
+ var logbox
13
+
14
+ // the checkbox to pause updating the log box
15
+ var pause_ckbx
16
+
17
+ // data from the log gets added to this string
18
+ // but its only written to the log box if we
19
+ // aren't paused.
20
+ var log_data
21
+
22
+ var new_log_level_regex = /Log level changed, now: (.*)$/;
23
+
24
+ // update the text in the log box unless the
25
+ // pause checkbox is checked
26
+ function update_logbox() {
27
+ if (pause_ckbx.checked) { return; }
28
+ logbox.value = log_data;
29
+ logbox.scrollTop = logbox.scrollHeight;
30
+ }
31
+
32
+ // start the stream
33
+ function start_log_stream() {
34
+ // always update the log level
35
+ get_current_log_level();
36
+ // return if already started
37
+ if (typeof(log_source) != "undefined") { return; }
38
+
39
+ logbox = document.getElementById("logbox");
40
+ pause_ckbx = document.getElementById("pause_log");
41
+
42
+ log_data = logbox.value;
43
+ log_source = new EventSource(log_stream_url);
44
+
45
+ // add incoming lines of data from the server
46
+ // to the in-memory cache
47
+ log_source.onmessage = function (event) {
48
+ var msg = event.data;
49
+ log_data = log_data + msg + "\n";
50
+ update_logbox();
51
+ var match = new_log_level_regex.exec(msg);
52
+ if (match) { update_log_level_selector(match[1]); }
53
+ };
54
+
55
+ // close the streams when client pages are closed.
56
+ // The server will see that the streams are closed
57
+ // and will remove the registrations as needed.
58
+ window.onbeforeunload = function() {
59
+ log_source.close();
60
+ return null;
61
+ }
62
+ }
63
+
64
+ // update the selector with the current log level from the server
65
+ function get_current_log_level() {
66
+ var url = '/current_log_level';
67
+ var xhttp = new XMLHttpRequest();
68
+
69
+ xhttp.onreadystatechange = function() {
70
+ if (this.readyState == 4 && this.status == 200) {
71
+ update_log_level_selector(xhttp.responseText);
72
+ }
73
+ };
74
+
75
+ xhttp.open("GET", url, true);
76
+ xhttp.send();
77
+ }
78
+
79
+ function update_log_level_selector(new_level) {
80
+ var new_idx;
81
+ switch(new_level) {
82
+ case 'fatal':
83
+ new_idx = 0;
84
+ break;
85
+ case 'error':
86
+ new_idx = 1;
87
+ break;
88
+ case 'warn':
89
+ new_idx = 2;
90
+ break;
91
+ case 'info':
92
+ new_idx = 3;
93
+ break;
94
+ case 'debug':
95
+ new_idx = 4;
96
+ break;
97
+ default:
98
+ new_idx = null;
99
+ }
100
+ document.getElementById("log_level_select").selectedIndex = new_idx;
101
+ }
@@ -23,5 +23,33 @@
23
23
  ###
24
24
  ###
25
25
 
26
+ module Chook
27
+
28
+ # the server
29
+ class Server < Sinatra::Base
30
+
31
+ HANDLE_EVENT_ROUTE = '/handle_webhook_event'.freeze
32
+
33
+ # before do
34
+ # break if request.path_info == Chook::Server::HANDLE_EVENT_ROUTE
35
+ # # break if request.path_info == '/' && session[:authed_admin]
36
+ # # redirect '/' unless session[:authed_admin]
37
+ # end
38
+
39
+ # log errors in production (in dev, they go to stdout and the browser)
40
+ error do
41
+ logger.error "ERROR: #{env['sinatra.error'].message}"
42
+ env['sinatra.error'].backtrace.each { |l| logger.error "..#{l}" }
43
+ 500
44
+ end
45
+
46
+ end # server
47
+
48
+ end # Chook
49
+
26
50
  require 'chook/server/routes/home'
27
51
  require 'chook/server/routes/handle_webhook_event'
52
+ require 'chook/server/routes/handle_by_name'
53
+ require 'chook/server/routes/handlers'
54
+ require 'chook/server/routes/login_logout'
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