chook 1.0.1.b1 → 1.1.5b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES.md +56 -0
  3. data/README.md +397 -145
  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 +252 -99
  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/subject/test_subject.rb +2 -2
  45. data/lib/chook/version.rb +1 -1
  46. metadata +78 -17
@@ -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