chook 1.0.0.b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +174 -0
  3. data/README.md +259 -0
  4. data/bin/chook-server +28 -0
  5. data/data/sample_handlers/RestAPIOperation-executable +91 -0
  6. data/data/sample_handlers/RestAPIOperation.rb +45 -0
  7. data/data/sample_handlers/SmartGroupComputerMembershipChange-executable +47 -0
  8. data/data/sample_handlers/SmartGroupComputerMembershipChange.rb +33 -0
  9. data/data/sample_jsons/ComputerAdded.json +27 -0
  10. data/data/sample_jsons/ComputerCheckIn.json +27 -0
  11. data/data/sample_jsons/ComputerInventoryCompleted.json +27 -0
  12. data/data/sample_jsons/ComputerPolicyFinished.json +27 -0
  13. data/data/sample_jsons/ComputerPushCapabilityChanged.json +27 -0
  14. data/data/sample_jsons/JSSShutdown.json +14 -0
  15. data/data/sample_jsons/JSSStartup.json +14 -0
  16. data/data/sample_jsons/MobileDeviceCheckIn.json +26 -0
  17. data/data/sample_jsons/MobileDeviceCommandCompleted.json +26 -0
  18. data/data/sample_jsons/MobileDeviceEnrolled.json +26 -0
  19. data/data/sample_jsons/MobileDevicePushSent.json +26 -0
  20. data/data/sample_jsons/MobileDeviceUnEnrolled.json +26 -0
  21. data/data/sample_jsons/PatchSoftwareTitleUpdated.json +14 -0
  22. data/data/sample_jsons/PushSent.json +11 -0
  23. data/data/sample_jsons/README +4 -0
  24. data/data/sample_jsons/RestAPIOperation.json +15 -0
  25. data/data/sample_jsons/SCEPChallenge.json +10 -0
  26. data/data/sample_jsons/SmartGroupComputerMembershipChange.json +13 -0
  27. data/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +13 -0
  28. data/lib/chook.rb +38 -0
  29. data/lib/chook/configuration.rb +198 -0
  30. data/lib/chook/event.rb +153 -0
  31. data/lib/chook/event/handled_event.rb +154 -0
  32. data/lib/chook/event/handled_event/handlers.rb +206 -0
  33. data/lib/chook/event/test_event.rb +140 -0
  34. data/lib/chook/event_handling.rb +40 -0
  35. data/lib/chook/event_testing.rb +43 -0
  36. data/lib/chook/foundation.rb +33 -0
  37. data/lib/chook/handled_events.rb +33 -0
  38. data/lib/chook/handled_subjects.rb +33 -0
  39. data/lib/chook/procs.rb +46 -0
  40. data/lib/chook/server.rb +121 -0
  41. data/lib/chook/server/routes.rb +27 -0
  42. data/lib/chook/server/routes/handle_webhook_event.rb +39 -0
  43. data/lib/chook/server/routes/home.rb +37 -0
  44. data/lib/chook/subject.rb +143 -0
  45. data/lib/chook/subject/computer.rb +121 -0
  46. data/lib/chook/subject/handled_subject.rb +84 -0
  47. data/lib/chook/subject/jss.rb +56 -0
  48. data/lib/chook/subject/mobile_device.rb +115 -0
  49. data/lib/chook/subject/patch_software_title_update.rb +55 -0
  50. data/lib/chook/subject/push.rb +38 -0
  51. data/lib/chook/subject/randomizers.rb +506 -0
  52. data/lib/chook/subject/rest_api_operation.rb +62 -0
  53. data/lib/chook/subject/samplers.rb +360 -0
  54. data/lib/chook/subject/scep_challenge.rb +32 -0
  55. data/lib/chook/subject/smart_group.rb +50 -0
  56. data/lib/chook/subject/test_subject.rb +195 -0
  57. data/lib/chook/subject/validators.rb +117 -0
  58. data/lib/chook/test_events.rb +33 -0
  59. data/lib/chook/test_subjects.rb +33 -0
  60. data/lib/chook/version.rb +32 -0
  61. metadata +129 -0
@@ -0,0 +1,50 @@
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
+ Chook::Subject.classes[Chook::Subject::SMART_GROUP] = {
26
+ name: {
27
+ validation: String,
28
+ randomizer: :word,
29
+ # sampler: :smart_group,
30
+ api_object_attribute: :name
31
+ },
32
+ smartGroup: {
33
+ validation: :boolean,
34
+ randomizer: Chook::Procs::ALWAYS_TRUE, # If this were false, it wouldn't be a Smart Group...
35
+ # sampler: Chook::Procs::ALWAYS_TRUE,
36
+ api_object_attribute: :is_smart
37
+ },
38
+ jssid: {
39
+ validation: Integer,
40
+ randomizer: :int,
41
+ # sampler: :smart_group_jssid,
42
+ api_object_attribute: :id
43
+ },
44
+ computer: { # SmartGroupComputerMembershipChange == true, SmartGroupMobileDeviceMembershipChange == false
45
+ validation: :boolean,
46
+ randomizer: :bool,
47
+ # sampler: ,
48
+ # api_object_attribute: :computer
49
+ }
50
+ }
@@ -0,0 +1,195 @@
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
+ # A subject that will be used with a TestEvent class, to be sent to
29
+ # a Webhook server, simulating one from the JSS.
30
+ #
31
+ # This is the parent class to all classes in the Chook::TestSubjects module.
32
+ #
33
+ # All constants, methods, and attributes that are common to TestSubject
34
+ # classes are defined here.
35
+ #
36
+ class TestSubject < Chook::Subject
37
+
38
+ # Dynamically generate the varios subclasses to TestSubject
39
+ # and store them in the TestSubjects module.
40
+ def self.generate_classes
41
+ Chook::Subject.classes.each do |classname, attribs|
42
+ # Don't redefine anything.
43
+ next if Chook::TestSubjects.const_defined? classname
44
+
45
+ # new subclass of Chook::TestSubject
46
+ new_class = Class.new(Chook::TestSubject) do
47
+ # add getter, setters, validators for all the attribs.
48
+ attribs.each do |attrib, deets|
49
+ # getter
50
+ attr_reader attrib
51
+ validator = deets[:validation]
52
+
53
+ # setter with validator
54
+ define_method("#{attrib}=") do |new_val|
55
+ if validator.is_a? Class
56
+ raise "Invalid value for #{attrib}, must be a #{validator}" unless new_val.is_a? validator
57
+ elsif !validator.nil?
58
+ raise "Invalid value for #{attrib}" unless Chook::Validators.send validator, new_val
59
+ end
60
+ instance_variable_set(('@' + attrib.to_s), new_val)
61
+ end # end define method
62
+ end # end do |attrib, deets|
63
+ end # end new_class
64
+ # set a class constant so each class knows it's name
65
+ new_class.const_set Chook::Subject::NAME_CONSTANT, classname
66
+
67
+ # add the class to the Chook::TestSubjects module
68
+ Chook::TestSubjects.const_set classname, new_class
69
+ end # end Chook::Subject.classes.each do |classname, attribs|
70
+ end # end generate_classes
71
+
72
+ # a random test subject,
73
+ def self.random
74
+ random_vals = {}
75
+ Chook::Subject.classes[].each do |attrib, deets|
76
+ random_vals[attrib] = Chook::Randomizers.send deets[:randomizer]
77
+ end # each do |attr_def|
78
+ new random_vals
79
+ end # end random
80
+
81
+ # a sampled test subject (real data from real JSS objects)
82
+ # NOTE: a valid ruby-jss JSS::APIConnection must exist
83
+ def self.sample(ids = 'random', api: JSS.api)
84
+ classname = self.const_get Chook::Subject::NAME_CONSTANT
85
+ ids = [ids] if ids.is_a? Integer
86
+ # !!Kernel.const_get('JSS::' + classname) rescue false
87
+ if classname == 'PatchSoftwareTitleUpdated'
88
+ all_ids = Chook::Samplers.all_patch_ids('blah', api: api)
89
+ else
90
+ all_ids = Kernel.const_get('JSS::' + classname).all_ids(api: api) # (api: api)
91
+ end
92
+ ids = [all_ids.sample] if ids == 'random'
93
+
94
+ ok = true
95
+ if ids.is_a? Array
96
+ ids.each { |id| ok == false unless id.is_a? Integer }
97
+ else
98
+ ok = false
99
+ end
100
+ raise 'ids must be an Array of Integers' unless ok
101
+
102
+ raw_samples = []
103
+ samples = []
104
+
105
+ valid_ids = ids & all_ids
106
+ raise "Invalid JSS IDs: #{ids}" if valid_ids.empty?
107
+
108
+ valid_ids.each do |id|
109
+ if classname == 'PatchSoftwareTitleUpdated'
110
+ raw_samples << Chook::Samplers.all_patches(api: api).select { |patch| patch[:id] == id }
111
+ raw_samples.flatten!
112
+ else
113
+ raw_samples << Kernel.const_get('JSS::' + classname).fetch(id: id, api: api)
114
+ end
115
+ end
116
+
117
+ raw_samples.each do |sample|
118
+ subject_details = {}
119
+ Chook::Subject.classes[classname].map do |subject_key, details|
120
+ extractor = details[:api_object_attribute]
121
+ subject_details[subject_key] =
122
+ case extractor
123
+ when Symbol
124
+ if classname == 'PatchSoftwareTitleUpdated'
125
+ # If there is a sampler method available, call it.
126
+ if details[:sampler]
127
+ extractor = details[:sampler]
128
+ Chook::Samplers.send(extractor, sample)
129
+ else
130
+ # Otherwise use it like a hash key
131
+ sample[extractor]
132
+ end
133
+ else
134
+ sample.send extractor
135
+ end
136
+ when Array
137
+ extractor = extractor.dup # If this doesn't get duplicated, shift will change details[:api_object_attribute]
138
+ method = extractor.shift
139
+ raw_hash_keys = extractor
140
+ method_result = sample.send(method)
141
+ raw_hash_keys.each { |key| method_result = method_result[key] }
142
+ method_result
143
+ when Proc
144
+ extractor.call sample
145
+ end
146
+ end # do |subject_key, details|
147
+ samples << Kernel.const_get('Chook::TestSubjects::' + classname).new(subject_details)
148
+ end # end samples.each do |sample|
149
+ samples
150
+ end # end sample
151
+
152
+ def json_hash
153
+ # Verify that input is a child of TestSubjects, raise if not
154
+ raise 'Invalid TestSubject' unless self.class.superclass == Chook::TestSubject
155
+ test_subject_attributes = Chook::Subject.classes[self.class.to_s.split('::')[-1]]
156
+ raw_hash_form = {}
157
+ test_subject_attributes.each do |attribute, details|
158
+ if details.keys.include? :to_json
159
+ raw_hash_form[attribute] = send(attribute).send details[:to_json]
160
+ else
161
+ raw_hash_form[attribute] = instance_variable_get('@' + attribute.to_s)
162
+ end
163
+ end # end test_subject_attributes.keys.each do |attribute, details|
164
+ raw_hash_form
165
+ end # end json_hash
166
+
167
+ # All the subclassses will inherit this constructor
168
+ #
169
+ # The argument is a Hash with keys from the appropriate keys defiend
170
+ # in Chook::Subject.classes
171
+ #
172
+ def initialize(subject_data = nil)
173
+ classname = self.class.const_get Chook::Subject::NAME_CONSTANT
174
+ attribs = Chook::Subject.classes[classname]
175
+
176
+ if subject_data
177
+ subject_data.each do |key, value|
178
+ # ignore unknown attributes. Shouldn't get any, but...
179
+ next unless attribs[key]
180
+
181
+ # does the value need conversion?
182
+ converter = attribs[key][:converter]
183
+ if converter
184
+ value = converter.is_a?(Symbol) ? value.send(converter) : converter.call(value)
185
+ end # if converter
186
+ instance_variable_set(('@' + key.to_s), value)
187
+ end # each key value
188
+ else
189
+ attribs.keys.each { |key| instance_variable_set(('@' + key.to_s), nil) }
190
+ end # if subject_data
191
+ end # init
192
+
193
+ end # class TestSubject
194
+
195
+ end # module
@@ -0,0 +1,117 @@
1
+ require 'uri'
2
+
3
+ module Chook
4
+
5
+ # A namespace to hold validation methods for use with
6
+ # Test Events and Test Subjects.
7
+ # Each method taks a value, and returns a boolean
8
+ # indicating the validity of the value.
9
+ #
10
+ module Validators
11
+
12
+ # Validate MAC Address
13
+ #
14
+ # @param [String] MAC address formatted String
15
+ # @return [Boolean]
16
+ #
17
+ def self.mac_address(mac)
18
+ mac =~ /^([a-f\d]{2}:){5}[a-f\d]{2}$/i ? true : false
19
+ end # end mac_address
20
+
21
+ # Validate E-mail Address
22
+ #
23
+ # @param [String] E-mail address formatted String e.g. FirstNameLastName@randomword.com
24
+ # @return [Boolean]
25
+ #
26
+ def self.email(email_address)
27
+ email_address =~ /^[a-zA-Z]([\w -]*[a-zA-Z])\@\w*\.\w*$/ ? true : false
28
+ end # end email
29
+
30
+ # Validate URL
31
+ #
32
+ # @param [String] URL formatted String
33
+ # @return [Boolean]
34
+ #
35
+ def self.url(url)
36
+ uri = URI.parse(url)
37
+ uri.is_a?(URI::HTTP) && !uri.host.nil? ? true : false
38
+ end # end url
39
+
40
+ # Validate Serial Number
41
+ #
42
+ # @param [String] Serial Number Formatted String
43
+ # @return [Boolean]
44
+ #
45
+ def self.serial_number(serial)
46
+ raise TypeError unless serial.is_a? String
47
+ serial_array = serial.scan(/\w/)
48
+ return false if serial.empty?
49
+ serial_array.each_with_index do |character, index|
50
+ return false unless (Chook::Randomizers::MOBILE_SERIAL_CHARACTER_SETS[index].include? character) || (Chook::Randomizers::COMPUTER_SERIAL_CHARACTER_SETS[index].include? character)
51
+ end
52
+ true
53
+ end # end serial_number
54
+
55
+ # Validate Push
56
+ #
57
+ # @param [String] Push Type
58
+ # @return [Boolean]
59
+ #
60
+ def self.push(push)
61
+ raise TypeError unless push.is_a? String
62
+ return false if push.empty?
63
+ return false unless Chook::Randomizers::PUSH_COMMANDS.include? push
64
+ true
65
+ end # end push
66
+
67
+ # Validate IMEI
68
+ #
69
+ # @param [String] A 17-15 digit sequence of numbers
70
+ # @return [Boolean]
71
+ #
72
+ def self.imei(imei)
73
+ imei_length = imei.delete(' ').size
74
+ (15...17).cover? imei_length
75
+ end # end imei
76
+
77
+ # Validate ICCID
78
+ #
79
+ # @param [String] ICCID
80
+ # @return [Boolean]
81
+ #
82
+ def self.iccid(iccid)
83
+ iccid_length = iccid.delete(' ').size
84
+ return true if iccid_length < 23
85
+ end # end iccid
86
+
87
+ # Validate Boolean
88
+ #
89
+ # @param [Boolean] Make sure input is valid Boolean, because Ruby doesn't have a Boolean Class
90
+ # @return [Boolean]
91
+ #
92
+ def self.boolean(true_or_false)
93
+ [true, false].include? true_or_false
94
+ end # end boolean
95
+
96
+ # Validate Patch
97
+ #
98
+ # @param [String] Name of a Patch Reporting Software Title
99
+ # @return [Boolean]
100
+ #
101
+ def self.patch(patch_name)
102
+ Chook::Randomizers::PATCH_SOFTWARE_TITLES.include? patch_name
103
+ end # end patch
104
+
105
+ # Validate Test Subject
106
+ #
107
+ # @param [String] Name of an Event class
108
+ # @param [Chook::TestSubjects] An instance of a Chook::TestSubjects subclass
109
+ # @return [Boolean]
110
+ #
111
+ def self.valid_test_subject(event_class, subject)
112
+ Chook::Event::EVENTS[event_class].include? subject.class.to_s.split('::')[-1]
113
+ end # end valid_test_subject
114
+
115
+ end # module validators
116
+
117
+ end # module Chook
@@ -0,0 +1,33 @@
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
+ # This class is a namespace holding all of the classes that are
29
+ # subclasses of Chook::TestEvent, q.v.
30
+ #
31
+ class TestEvents; end # class TestEvents
32
+
33
+ end # class Chook
@@ -0,0 +1,33 @@
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
+ # This module is a namespace holding all of the classes that are
29
+ # subclasses of Chook::TestSubject, q.v.
30
+ #
31
+ module TestSubjects; end # module TestSubjects
32
+
33
+ end # module
@@ -0,0 +1,32 @@
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 Chook
28
+
29
+ ### The version of the Chook framework
30
+ VERSION = '1.0.0.b1'.freeze
31
+
32
+ end # module