esp_sdk 1.1.0 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.rubocop.yml +53 -6
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +8 -2
  6. data/Gemfile.lock +171 -0
  7. data/Guardfile +47 -0
  8. data/README.md +230 -5
  9. data/Rakefile +14 -1
  10. data/assets/logo.png +0 -0
  11. data/bin/esp_console +71 -0
  12. data/esp_sdk.gemspec +27 -18
  13. data/lib/esp/exceptions.rb +3 -0
  14. data/lib/esp/extensions/active_resource/formats/json_api_format.rb +105 -0
  15. data/lib/esp/extensions/active_resource/paginated_collection.rb +198 -0
  16. data/lib/esp/extensions/active_resource/validations.rb +45 -0
  17. data/lib/esp/resources/alert.rb +135 -0
  18. data/lib/esp/resources/cloud_trail_event.rb +45 -0
  19. data/lib/esp/resources/concerns/stat_totals.rb +79 -0
  20. data/lib/esp/resources/contact_request.rb +42 -0
  21. data/lib/esp/resources/custom_signature.rb +224 -0
  22. data/lib/esp/resources/dashboard.rb +31 -0
  23. data/lib/esp/resources/external_account.rb +89 -0
  24. data/lib/esp/resources/organization.rb +61 -0
  25. data/lib/esp/resources/region.rb +46 -0
  26. data/lib/esp/resources/report.rb +100 -0
  27. data/lib/esp/resources/resource.rb +66 -0
  28. data/lib/esp/resources/service.rb +31 -0
  29. data/lib/esp/resources/signature.rb +106 -0
  30. data/lib/esp/resources/stat.rb +124 -0
  31. data/lib/esp/resources/stat_custom_signature.rb +121 -0
  32. data/lib/esp/resources/stat_region.rb +121 -0
  33. data/lib/esp/resources/stat_service.rb +121 -0
  34. data/lib/esp/resources/stat_signature.rb +121 -0
  35. data/lib/esp/resources/sub_organization.rb +69 -0
  36. data/lib/esp/resources/suppression/region.rb +99 -0
  37. data/lib/esp/resources/suppression/signature.rb +107 -0
  38. data/lib/esp/resources/suppression/unique_identifier.rb +60 -0
  39. data/lib/esp/resources/suppression.rb +86 -0
  40. data/lib/esp/resources/tag.rb +45 -0
  41. data/lib/esp/resources/team.rb +79 -0
  42. data/lib/esp/resources/user.rb +46 -0
  43. data/lib/esp/version.rb +3 -0
  44. data/lib/esp.rb +95 -0
  45. data/lib/esp_sdk.rb +9 -45
  46. data/lib/tasks/rubocop.rake +2 -0
  47. data/lib/tasks/testing.rake +3 -0
  48. data/rdoc/ActiveResource/Formats.html +176 -0
  49. data/rdoc/ActiveResource/PaginatedCollection.html +910 -0
  50. data/rdoc/ActiveResource.html +180 -0
  51. data/rdoc/ESP/Alert.html +771 -0
  52. data/rdoc/ESP/CloudTrailEvent.html +375 -0
  53. data/rdoc/ESP/ContactRequest.html +366 -0
  54. data/rdoc/ESP/CustomSignature.html +746 -0
  55. data/rdoc/ESP/Dashboard.html +355 -0
  56. data/rdoc/ESP/ExternalAccount.html +565 -0
  57. data/rdoc/ESP/Organization.html +590 -0
  58. data/rdoc/ESP/Region.html +399 -0
  59. data/rdoc/ESP/Report.html +622 -0
  60. data/rdoc/ESP/Service.html +380 -0
  61. data/rdoc/ESP/Signature.html +555 -0
  62. data/rdoc/ESP/Stat.html +1778 -0
  63. data/rdoc/ESP/StatCustomSignature.html +1599 -0
  64. data/rdoc/ESP/StatRegion.html +1598 -0
  65. data/rdoc/ESP/StatService.html +1598 -0
  66. data/rdoc/ESP/StatSignature.html +1598 -0
  67. data/rdoc/ESP/SubOrganization.html +540 -0
  68. data/rdoc/ESP/Suppression/Region.html +454 -0
  69. data/rdoc/ESP/Suppression/Signature.html +470 -0
  70. data/rdoc/ESP/Suppression/UniqueIdentifier.html +417 -0
  71. data/rdoc/ESP/Suppression.html +649 -0
  72. data/rdoc/ESP/Tag.html +371 -0
  73. data/rdoc/ESP/Team.html +584 -0
  74. data/rdoc/ESP/User.html +483 -0
  75. data/rdoc/ESP.html +546 -0
  76. data/rdoc/README_md.html +501 -0
  77. data/rdoc/created.rid +30 -0
  78. data/rdoc/images/add.png +0 -0
  79. data/rdoc/images/arrow_up.png +0 -0
  80. data/rdoc/images/brick.png +0 -0
  81. data/rdoc/images/brick_link.png +0 -0
  82. data/rdoc/images/bug.png +0 -0
  83. data/rdoc/images/bullet_black.png +0 -0
  84. data/rdoc/images/bullet_toggle_minus.png +0 -0
  85. data/rdoc/images/bullet_toggle_plus.png +0 -0
  86. data/rdoc/images/date.png +0 -0
  87. data/rdoc/images/delete.png +0 -0
  88. data/rdoc/images/find.png +0 -0
  89. data/rdoc/images/loadingAnimation.gif +0 -0
  90. data/rdoc/images/macFFBgHack.png +0 -0
  91. data/rdoc/images/package.png +0 -0
  92. data/rdoc/images/page_green.png +0 -0
  93. data/rdoc/images/page_white_text.png +0 -0
  94. data/rdoc/images/page_white_width.png +0 -0
  95. data/rdoc/images/plugin.png +0 -0
  96. data/rdoc/images/ruby.png +0 -0
  97. data/rdoc/images/tag_blue.png +0 -0
  98. data/rdoc/images/tag_green.png +0 -0
  99. data/rdoc/images/transparent.png +0 -0
  100. data/rdoc/images/wrench.png +0 -0
  101. data/rdoc/images/wrench_orange.png +0 -0
  102. data/rdoc/images/zoom.png +0 -0
  103. data/rdoc/index.html +134 -0
  104. data/rdoc/js/darkfish.js +155 -0
  105. data/rdoc/js/jquery.js +4 -0
  106. data/rdoc/js/navigation.js +142 -0
  107. data/rdoc/js/search.js +94 -0
  108. data/rdoc/js/search_index.js +1 -0
  109. data/rdoc/js/searcher.js +228 -0
  110. data/rdoc/rdoc.css +595 -0
  111. data/rdoc/table_of_contents.html +927 -0
  112. data/test/esp/extensions/active_resource/formats/json_api_format_test.rb +109 -0
  113. data/test/esp/extensions/active_resource/paginated_collection_test.rb +435 -0
  114. data/test/esp/extensions/active_resource/validations_test.rb +59 -0
  115. data/test/esp/resources/alert_test.rb +263 -0
  116. data/test/esp/resources/cloud_trail_event_test.rb +98 -0
  117. data/test/esp/resources/contact_request_test.rb +73 -0
  118. data/test/esp/resources/custom_signature_test.rb +241 -0
  119. data/test/esp/resources/dashboard_test.rb +71 -0
  120. data/test/esp/resources/external_account_test.rb +125 -0
  121. data/test/esp/resources/organization_test.rb +175 -0
  122. data/test/esp/resources/region_test.rb +84 -0
  123. data/test/esp/resources/report_test.rb +180 -0
  124. data/test/esp/resources/resource_test.rb +183 -0
  125. data/test/esp/resources/service_test.rb +64 -0
  126. data/test/esp/resources/signature_test.rb +177 -0
  127. data/test/esp/resources/stat_custom_signature_test.rb +115 -0
  128. data/test/esp/resources/stat_region_test.rb +114 -0
  129. data/test/esp/resources/stat_service_test.rb +114 -0
  130. data/test/esp/resources/stat_signature_test.rb +115 -0
  131. data/test/esp/resources/stat_test.rb +159 -0
  132. data/test/esp/resources/sub_organization_test.rb +127 -0
  133. data/test/esp/resources/suppression/region_test.rb +115 -0
  134. data/test/esp/resources/suppression/signature_test.rb +117 -0
  135. data/test/esp/resources/suppression/unique_identifier_test.rb +79 -0
  136. data/test/esp/resources/suppression_test.rb +226 -0
  137. data/test/esp/resources/tag_test.rb +98 -0
  138. data/test/esp/resources/team_test.rb +140 -0
  139. data/test/esp/resources/user_test.rb +113 -0
  140. data/test/esp_test.rb +139 -0
  141. data/test/factories/alerts.rb +234 -0
  142. data/test/factories/cloud_trail_events.rb +16 -0
  143. data/test/factories/contact_requests.rb +14 -0
  144. data/test/factories/custom_signatures.rb +30 -0
  145. data/test/factories/dashboards.rb +91 -0
  146. data/test/factories/errors.rb +24 -0
  147. data/test/factories/external_accounts.rb +44 -0
  148. data/test/factories/organizations.rb +48 -0
  149. data/test/factories/regions.rb +9 -0
  150. data/test/factories/reports.rb +56 -0
  151. data/test/factories/services.rb +12 -0
  152. data/test/factories/signatures.rb +28 -0
  153. data/test/factories/stat_custom_signatures.rb +97 -0
  154. data/test/factories/stat_regions.rb +97 -0
  155. data/test/factories/stat_services.rb +97 -0
  156. data/test/factories/stat_signautures.rb +97 -0
  157. data/test/factories/stats.rb +129 -0
  158. data/test/factories/sub_organizations.rb +34 -0
  159. data/test/factories/suppression/regions.rb +90 -0
  160. data/test/factories/suppression/signatures.rb +117 -0
  161. data/test/factories/suppression/unique_identifiers.rb +111 -0
  162. data/test/factories/suppressions.rb +71 -0
  163. data/test/factories/tags.rb +12 -0
  164. data/test/factories/teams.rb +32 -0
  165. data/test/factories/users.rb +54 -0
  166. data/test/json_strategy.rb +25 -0
  167. data/test/test_helper.rb +44 -5
  168. metadata +387 -119
  169. data/bin/esp_repl +0 -60
  170. data/lib/esp_sdk/api.rb +0 -33
  171. data/lib/esp_sdk/client.rb +0 -62
  172. data/lib/esp_sdk/configure.rb +0 -40
  173. data/lib/esp_sdk/end_points/base.rb +0 -102
  174. data/lib/esp_sdk/end_points/contact_requests.rb +0 -6
  175. data/lib/esp_sdk/end_points/custom_signatures.rb +0 -41
  176. data/lib/esp_sdk/end_points/dashboard.rb +0 -35
  177. data/lib/esp_sdk/end_points/external_accounts.rb +0 -9
  178. data/lib/esp_sdk/end_points/organizations.rb +0 -6
  179. data/lib/esp_sdk/end_points/reports.rb +0 -6
  180. data/lib/esp_sdk/end_points/services.rb +0 -6
  181. data/lib/esp_sdk/end_points/signatures.rb +0 -39
  182. data/lib/esp_sdk/end_points/sub_organizations.rb +0 -6
  183. data/lib/esp_sdk/end_points/teams.rb +0 -6
  184. data/lib/esp_sdk/end_points/users.rb +0 -6
  185. data/lib/esp_sdk/exceptions.rb +0 -8
  186. data/lib/esp_sdk/extensions/rest_client/request.rb +0 -9
  187. data/lib/esp_sdk/repl.rb +0 -61
  188. data/lib/esp_sdk/version.rb +0 -3
  189. data/test/esp_sdk/api_test.rb +0 -36
  190. data/test/esp_sdk/client_test.rb +0 -129
  191. data/test/esp_sdk/configure_test.rb +0 -65
  192. data/test/esp_sdk/end_points/.keep +0 -0
  193. data/test/esp_sdk/end_points/base_test.rb +0 -230
  194. data/test/esp_sdk/end_points/custom_signatures_test.rb +0 -90
  195. data/test/esp_sdk/end_points/dashboard_test.rb +0 -55
  196. data/test/esp_sdk/end_points/external_accounts_test.rb +0 -20
  197. data/test/esp_sdk/end_points/signatures_test.rb +0 -83
  198. data/test/esp_sdk/exceptions_test.rb +0 -41
  199. data/test/esp_sdk_test.rb +0 -70
@@ -0,0 +1,79 @@
1
+ module ESP::StatTotals # :nodoc:
2
+ # Not Implemented. You cannot create or update a Stat.
3
+ def save
4
+ fail ESP::NotImplementedError
5
+ end
6
+
7
+ # Not Implemented. You cannot delete a Stat.
8
+ def destroy
9
+ fail ESP::NotImplementedError
10
+ end
11
+
12
+ # We only add new_1w* and old* fields as the new_1w field includes the counts from new_1h and new_1d.
13
+ def total
14
+ attributes.select { |a, _v| a.match(/new_1w|old/) }.values.reduce(:+)
15
+ end
16
+
17
+ def total_suppressed
18
+ attributes.select { |a, _v| a.match(/suppressed_/) }.values.reduce(:+)
19
+ end
20
+
21
+ %w(fail warn error pass info).each do |status|
22
+ # Defines the following methods:
23
+ # Stat#total_pass
24
+ # Stat#total_fail
25
+ # Stat#total_warn
26
+ # Stat#total_error
27
+ # Stat#total_info
28
+ define_method "total_#{status}" do
29
+ attributes.select { |a, _v| a.match(/new_1w|old/) && a.match(/#{status}/) }.values.reduce(:+)
30
+ end
31
+
32
+ # Defines the following methods:
33
+ # Stat#total_new_1h_pass
34
+ # Stat#total_new_1h_fail
35
+ # Stat#total_new_1h_warn
36
+ # Stat#total_new_1h_error
37
+ # Stat#total_new_1h_info
38
+ # Stat#total_new_1d_pass
39
+ # Stat#total_new_1d_fail
40
+ # Stat#total_new_1d_warn
41
+ # Stat#total_new_1d_error
42
+ # Stat#total_new_1d_info
43
+ # Stat#total_new_1w_pass
44
+ # Stat#total_new_1w_fail
45
+ # Stat#total_new_1w_error
46
+ # Stat#total_new_1w_info
47
+ # Stat#total_new_1w_warn
48
+ # Stat#total_old_fail
49
+ # Stat#total_old_pass
50
+ # Stat#total_old_warn
51
+ # Stat#total_old_error
52
+ # Stat#total_old_info
53
+ %w(new_1h new_1d new_1w old).each do |time|
54
+ define_method "total_#{time}_#{status}" do
55
+ attributes.select { |a| a.match(/#{time}/) && a.match(/#{status}/) }.values.reduce(:+)
56
+ end
57
+ end
58
+
59
+ # Defines the following methods:
60
+ # Stat#total_suppressed_pass
61
+ # Stat#total_suppressed_fail
62
+ # Stat#total_suppressed_warn
63
+ # Stat#total_suppressed_error
64
+ define_method "total_suppressed_#{status}" do
65
+ attributes.select { |a| a.match(/suppressed_/) && a.match(/#{status}/) }.values.reduce(:+)
66
+ end
67
+ end
68
+
69
+ # Defines the following methods:
70
+ # Stat#total_new_1h
71
+ # Stat#total_new_1d
72
+ # Stat#total_new_1w
73
+ # Stat#total_old
74
+ %w(new_1h new_1d new_1w old).each do |time|
75
+ define_method "total_#{time}" do
76
+ attributes.select { |a| a.match(/#{time}/) }.values.reduce(:+)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,42 @@
1
+ module ESP
2
+ # Use contact requests to send a support or feature request to Evident.io.
3
+ class ContactRequest < ESP::Resource
4
+ # Not Implemented. You cannot search for ContactRequest.
5
+ def self.find(*)
6
+ fail ESP::NotImplementedError
7
+ end
8
+
9
+ # Not Implemented. You cannot update a ContactRequest.
10
+ def update
11
+ fail ESP::NotImplementedError
12
+ end
13
+
14
+ # Not Implemented. You cannot destroy a ContactRequest.
15
+ def destroy
16
+ fail ESP::NotImplementedError
17
+ end
18
+
19
+ # :method: create(attributes={})
20
+ # Create a contact request.
21
+ #
22
+ # ==== Parameter
23
+ #
24
+ # +attributes+ | Required | A hash of contact request attributes
25
+ #
26
+ # ===== Valid Attributes
27
+ #
28
+ # +title+ | Required | Subject of your message
29
+ #
30
+ # +description+ | Required | Body of your message
31
+ #
32
+ # +request_type+ | Required | Type of contact request. Supported values are `support` for support requests and `feature` for a feature request
33
+ #
34
+ #
35
+ # :call-seq:
36
+ # create(attributes={})
37
+ #
38
+ # ==== Example
39
+ #
40
+ # contact_request = ESP::ContactRequest.create(request_type: 'feature', title: 'My great feature idea', description: 'This is my idea for a really useful feature...')
41
+ end
42
+ end
@@ -0,0 +1,224 @@
1
+ module ESP
2
+ class CustomSignature < ESP::Resource
3
+ ##
4
+ # The organization this custom signature belongs to.
5
+ belongs_to :organization, class_name: 'ESP::Organization'
6
+
7
+ # Run a custom signature that has not been saved. Useful for debugging a custom signature.
8
+ # Returns a collection of alerts.
9
+ # Throws an error if not successful.
10
+ #
11
+ # ==== Parameters
12
+ #
13
+ # +arguments+ | Required | A hash of run arguments
14
+ #
15
+ # ===== Valid Arguments
16
+ #
17
+ # +external_account_id+ | Required | The ID of the external account to run this custom signature against
18
+ #
19
+ # +signature+ | Required | The code for this custom signature
20
+ #
21
+ # +language+ | Required | The language of the custom signature. Possible values are `ruby` or `javascript`
22
+ #
23
+ # +regions+ | Required | Array of region names to run this custom signature against
24
+ #
25
+ # ==== Example
26
+ # signature = "# Demo Ruby Signature\r\nconfigure do |c|\r\n # Set regions to run in. Remove this line to run in all regions.\r\n c.valid_regions = [:us_east_1]\r\n # Override region to display as global. Useful when checking resources\r\n # like IAM that do not have a specific region.\r\n c.display_as = :global\r\n # deep_inspection works with set_data to automically collect\r\n # data fields for each alert. Not required.\r\n c.deep_inspection = [:users]\r\nend\r\n\r\n# Required perform method\r\ndef perform(aws)\r\n list_users = aws.iam.list_users\r\n count = list_users[:users].count\r\n\r\n # Set data for deep_inspection to use\r\n set_data(list_users)\r\n\r\n if count == 0\r\n fail(user_count: count, condition: 'count == 0')\r\n else\r\n pass(user_count: count, condition: 'count >= 1')\r\n end\r\nend\r\n"
27
+ # alerts = ESP::CustomSignature.run!(external_account_id: 3, regions: ['us_east_1'], language: 'ruby', signature: signature)
28
+ def self.run!(arguments = {})
29
+ result = run(arguments)
30
+ return result if result.is_a?(ActiveResource::Collection)
31
+ result.message = result.errors.full_messages.join(' ')
32
+ fail(ActiveResource::ResourceInvalid.new(result)) # rubocop:disable Style/RaiseArgs
33
+ end
34
+
35
+ # Run a custom signature that has not been saved. Useful for debugging a custom signature.
36
+ # Returns a collection of alerts.
37
+ # If not successful, returns a CustomSignature object with the errors object populated.
38
+ #
39
+ # ==== Parameters
40
+ #
41
+ # +arguments+ | Required | A hash of run arguments
42
+ #
43
+ # ===== Valid Arguments
44
+ #
45
+ # +external_account_id+ | Required | The ID of the external account to run this custom signature against
46
+ #
47
+ # +signature+ | Required | The code for this custom signature
48
+ #
49
+ # +language+ | Required | The language of the custom signature. Possible values are `ruby` or `javascript`
50
+ #
51
+ # +regions+ | Required | Array of region names to run this custom signature against
52
+ #
53
+ # ==== Example
54
+ # signature = "# Demo Ruby Signature\r\nconfigure do |c|\r\n # Set regions to run in. Remove this line to run in all regions.\r\n c.valid_regions = [:us_east_1]\r\n # Override region to display as global. Useful when checking resources\r\n # like IAM that do not have a specific region.\r\n c.display_as = :global\r\n # deep_inspection works with set_data to automically collect\r\n # data fields for each alert. Not required.\r\n c.deep_inspection = [:users]\r\nend\r\n\r\n# Required perform method\r\ndef perform(aws)\r\n list_users = aws.iam.list_users\r\n count = list_users[:users].count\r\n\r\n # Set data for deep_inspection to use\r\n set_data(list_users)\r\n\r\n if count == 0\r\n fail(user_count: count, condition: 'count == 0')\r\n else\r\n pass(user_count: count, condition: 'count >= 1')\r\n end\r\nend\r\n"
55
+ # alerts = ESP::CustomSignature.run(external_account_id: 3, regions: ['us_east_1'], language: 'ruby', signature: signature)
56
+ def self.run(arguments = {})
57
+ arguments = arguments.with_indifferent_access
58
+ arguments[:regions] = Array(arguments[:regions])
59
+ new(arguments).run
60
+ end
61
+
62
+ # Run this custom signature instance.
63
+ # Returns a collection of alerts.
64
+ # Throws an error if not successful.
65
+ #
66
+ # ==== Parameters
67
+ #
68
+ # +arguments+ | Required | A hash of run arguments
69
+ #
70
+ # ===== Valid Arguments
71
+ #
72
+ # +external_account_id+ | Required | The ID of the external account to run this custom signature against
73
+ #
74
+ # +regions+ | Required | Array of region names to run this custom signature against
75
+ #
76
+ # ==== Example
77
+ # custom_signature = ESP::CustomSignature.find(365)
78
+ # alerts = custom_signature.run!(external_account_id: 3, regions: ['us_east_1'])
79
+ def run!(arguments = {})
80
+ result = run(arguments)
81
+ return result if result.is_a?(ActiveResource::Collection)
82
+ self.message = errors.full_messages.join(' ')
83
+ fail(ActiveResource::ResourceInvalid.new(self)) # rubocop:disable Style/RaiseArgs
84
+ end
85
+
86
+ # Run this custom signature instance.
87
+ # Returns a collection of alerts.
88
+ # If not successful, returns a CustomSignature object with the errors object populated.
89
+ #
90
+ # ==== Parameters
91
+ #
92
+ # +arguments+ | Required | A hash of run arguments
93
+ #
94
+ # ===== Valid Arguments
95
+ #
96
+ # +external_account_id+ | Required | The ID of the external account to run this custom signature against
97
+ #
98
+ # +regions+ | Required | Array of region names to run this custom signature against
99
+ #
100
+ # ==== Example
101
+ # custom_signature = ESP::CustomSignature.find(365)
102
+ # alerts = custom_signature.run(external_account_id: 3, regions: ['us_east_1'])
103
+ def run(arguments = {})
104
+ arguments = arguments.with_indifferent_access
105
+
106
+ attributes['external_account_id'] ||= arguments[:external_account_id]
107
+ attributes['regions'] ||= Array(arguments[:regions])
108
+
109
+ response = connection.post endpoint, to_json
110
+ ESP::Alert.send(:instantiate_collection, self.class.format.decode(response.body))
111
+ rescue ActiveResource::BadRequest, ActiveResource::ResourceInvalid, ActiveResource::ResourceNotFound => error
112
+ load_remote_errors(error, true)
113
+ self.code = error.response.code
114
+ self
115
+ end
116
+
117
+ # Create a suppression for this custom signature.
118
+ #
119
+ # ==== Parameter
120
+ #
121
+ # +arguments+ | Required | A hash of signature suppression attributes
122
+ #
123
+ # ===== Valid Arguments
124
+ #
125
+ # +regions+ | Required | An array of region names to suppress.
126
+ #
127
+ # +external_account_ids+ | Required | An Array of the external accounts identified by +external_account_id+ to suppress the signature or custom signature on.
128
+ #
129
+ # +reason+ | Required | The reason for creating the suppression.
130
+ #
131
+ # ==== Example
132
+ # suppress(regions: ['us_east_1'], external_account_ids: [5], reason: 'My very good reason for creating this suppression')
133
+ def suppress(arguments = {})
134
+ arguments = arguments.with_indifferent_access
135
+ ESP::Suppression::Signature.create(custom_signature_ids: [id], regions: Array(arguments[:regions]), external_account_ids: Array(arguments[:external_account_ids]), reason: arguments[:reason])
136
+ end
137
+
138
+ ##
139
+ # :singleton-method: find
140
+ # Find a CustomSignature by id
141
+ #
142
+ # ==== Parameter
143
+ #
144
+ # +id+ | Required | The ID of the custom signature to retrieve
145
+ #
146
+ # :call-seq:
147
+ # find(id)
148
+
149
+ # :singleton-method: all
150
+ # Return a paginated CustomSignature list
151
+
152
+ # :singleton-method: create
153
+ # Create a CustomSignature
154
+ # :call-seq:
155
+ # create(attributes={})
156
+ #
157
+ # ==== Parameter
158
+ #
159
+ # +attributes+ | Required | A hash of custom signature attributes
160
+ #
161
+ # ===== Valid Attributes
162
+ #
163
+ # +active+ | Not Required | Flag that determines if this custom signature should run on reports
164
+ #
165
+ # +description+ | Not Required | The description of the custom signature that is displayed on alerts
166
+ #
167
+ # +identifier+ | Required | The identifier to use for the custom signature. Common format is AWS:<Service>-<Number> such as AWS:IAM-001
168
+ #
169
+ # +language+ | Required | The language of the custom signature. Possible values are `ruby` or `javascript`
170
+ #
171
+ # +name+ | Required | The name of the custom signature
172
+ #
173
+ # +resolution+ | Not Required | Details for how to resolve this custom signature that is displayed on alerts
174
+ #
175
+ # +risk_level+ | Required | The risk-level of the problem identified by the custom signature
176
+ #
177
+ # +signature+ | Required | The code for this custom signature
178
+ #
179
+ # ==== Example
180
+ #
181
+ # signature = "# Demo Ruby Signature\r\nconfigure do |c|\r\n # Set regions to run in. Remove this line to run in all regions.\r\n c.valid_regions = [:us_east_1]\r\n # Override region to display as global. Useful when checking resources\r\n # like IAM that do not have a specific region.\r\n c.display_as = :global\r\n # deep_inspection works with set_data to automically collect\r\n # data fields for each alert. Not required.\r\n c.deep_inspection = [:users]\r\nend\r\n\r\n# Required perform method\r\ndef perform(aws)\r\n list_users = aws.iam.list_users\r\n count = list_users[:users].count\r\n\r\n # Set data for deep_inspection to use\r\n set_data(list_users)\r\n\r\n if count == 0\r\n fail(user_count: count, condition: 'count == 0')\r\n else\r\n pass(user_count: count, condition: 'count >= 1')\r\n end\r\nend\r\n"
182
+ # custom_signature = ESP::CustomSignature.create(signature: signature, description: "A test custom signature.", identifier: "AWS::IAM::001", language: "ruby", name: "Test Signature", risk_level: "Medium")
183
+
184
+ # :method: save
185
+ # Create or update a CustomSignature
186
+ #
187
+ # ===== Valid Attributes
188
+ #
189
+ # +active+ | Not Required | Flag that determines if this custom signature should run on reports
190
+ #
191
+ # +description+ | Not Required | The description of the custom signature that is displayed on alerts
192
+ #
193
+ # +identifier+ | Required | The identifier to use for the custom signature. Common format is AWS:<Service>-<Number> such as AWS:IAM-001
194
+ #
195
+ # +language+ | Required | The language of the custom signature. Possible values are `ruby` or `javascript`
196
+ #
197
+ # +name+ | Required | The name of the custom signature
198
+ #
199
+ # +resolution+ | Not Required | Details for how to resolve this custom signature that is displayed on alerts
200
+ #
201
+ # +risk_level+ | Required | The risk-level of the problem identified by the custom signature
202
+ #
203
+ # +signature+ | Required | The code for this custom signature
204
+ #
205
+ # ==== Example
206
+ #
207
+ # signature = "# Demo Ruby Signature\r\nconfigure do |c|\r\n # Set regions to run in. Remove this line to run in all regions.\r\n c.valid_regions = [:us_east_1]\r\n # Override region to display as global. Useful when checking resources\r\n # like IAM that do not have a specific region.\r\n c.display_as = :global\r\n # deep_inspection works with set_data to automically collect\r\n # data fields for each alert. Not required.\r\n c.deep_inspection = [:users]\r\nend\r\n\r\n# Required perform method\r\ndef perform(aws)\r\n list_users = aws.iam.list_users\r\n count = list_users[:users].count\r\n\r\n # Set data for deep_inspection to use\r\n set_data(list_users)\r\n\r\n if count == 0\r\n fail(user_count: count, condition: 'count == 0')\r\n else\r\n pass(user_count: count, condition: 'count >= 1')\r\n end\r\nend\r\n"
208
+ # custom_signature = ESP::CustomSignature.new(signature: signature, description: "A test custom signature.", identifier: "AWS::IAM::001", language: "ruby", name: "Test Signature", risk_level: "Medium")
209
+ # custom_signature.save
210
+
211
+ # :method: destroy
212
+ # Delete a CustomSignature
213
+
214
+ private
215
+
216
+ def endpoint
217
+ if id.present?
218
+ "#{self.class.prefix}custom_signatures/#{id}/run.json"
219
+ else
220
+ "#{self.class.prefix}custom_signatures/run.json"
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,31 @@
1
+ module ESP
2
+ class Dashboard < ESP::Resource
3
+ # Not Implemented. You cannot search for Suppression::Region.
4
+ #
5
+ # Regular ARELlike methods are disabled.
6
+ def self.find(*)
7
+ fail ESP::NotImplementedError, 'Regular ARELlike methods are disabled. Use either the .recent method.'
8
+ end
9
+
10
+ # Not Implemented. You cannot create or update a Dashboard.
11
+ def save
12
+ fail ESP::NotImplementedError
13
+ end
14
+
15
+ # Not Implemented. You cannot destroy a Dashboard.
16
+ def destroy
17
+ fail ESP::NotImplementedError
18
+ end
19
+
20
+ # Returns a Dashboard object with data from reports run in the last 2 hours
21
+ #
22
+ # ==== Note
23
+ #
24
+ # The dashboard is used internally for the dashboard page on esp.evident.io and is therefore not considered
25
+ # part of the public API and may change without notice.
26
+ def self.recent
27
+ # call find_every directly since find is overridden/not implemented
28
+ find_every from: "#{prefix}dashboard/recent.#{format.extension}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,89 @@
1
+ module ESP
2
+ class ExternalAccount < ESP::Resource
3
+ ##
4
+ # The organization the external account belongs to.
5
+ belongs_to :organization, class_name: 'ESP::Organization'
6
+
7
+ ##
8
+ # The sub_organization the external account belongs to.
9
+ belongs_to :sub_organization, class_name: 'ESP::SubOrganization'
10
+
11
+ ##
12
+ # The team the external account belongs to.
13
+ belongs_to :team, class_name: 'ESP::Team'
14
+
15
+ # Helper to generate an external id.
16
+ # Called automatically when creating an ExternalAccount if +external_id+ is not already set.
17
+ def generate_external_id
18
+ SecureRandom.uuid
19
+ end
20
+
21
+ # This instance method is called by the #save method when new? is true.
22
+ def create # :nodoc:
23
+ attributes['external_id'] ||= generate_external_id
24
+ super
25
+ end
26
+
27
+ ##
28
+ # :singleton-method: find
29
+ # Find an ExternalAccount by id
30
+ #
31
+ # ==== Parameter
32
+ #
33
+ # +id+ | Required | The ID of the external account to retrieve
34
+ #
35
+ # :call-seq:
36
+ # find(id)
37
+
38
+ # :singleton-method: all
39
+ # Return a paginated CustomSignature list
40
+
41
+ # :singleton-method: create
42
+ # Create an ExternalAccount.
43
+ # :call-seq:
44
+ # create(attributes={})
45
+ #
46
+ # ==== Parameter
47
+ #
48
+ # +attributes+ | Required | A hash of external account attributes
49
+ #
50
+ # ===== Valid Attributes
51
+ #
52
+ # +arn+ | Required | Amazon Resource Name for the IAM role
53
+ #
54
+ # +external_id+ | Required | External identifier set on the role. This will be set by calling #generate_external_id if not already set.
55
+ #
56
+ # +name+ | Not Required | The name for this external account
57
+ #
58
+ # +sub_organization_id+ | Required | The ID of the sub organization the external account will belong to
59
+ #
60
+ # +team_id+ | Required | The ID of the team the external account will belong to
61
+ #
62
+ # ==== Example
63
+ #
64
+ # external_account = ESP::ExternalAccount.create(arn: 'arn:from:aws', external_id: 'c40e6af4-a5a0-422a-9a42-3d7d236c3428', sub_organization_id: 4, team_id: 8)
65
+
66
+ # :method: save
67
+ # Create or update an ExternalAccount.
68
+ #
69
+ # ===== Valid Attributes
70
+ #
71
+ # +arn+ | Required | Amazon Resource Name for the IAM role
72
+ #
73
+ # +external_id+ | Required | External identifier set on the role. This will be set by calling #generate_external_id if not already set.
74
+ #
75
+ # +name+ | Not Required | The name for this external account
76
+ #
77
+ # +sub_organization_id+ | Required | The ID of the sub organization the external account will belong to
78
+ #
79
+ # +team_id+ | Required | The ID of the team the external account will belong to
80
+ #
81
+ # ==== Example
82
+ #
83
+ # external_account = ESP::ExternalAccount.new(arn: 'arn:from:aws', external_id: 'c40e6af4-a5a0-422a-9a42-3d7d236c3428', sub_organization_id: 4, team_id: 8)
84
+ # external_account.save
85
+
86
+ # :method: destroy
87
+ # Delete a CustomSignature
88
+ end
89
+ end
@@ -0,0 +1,61 @@
1
+ module ESP
2
+ class Organization < ESP::Resource
3
+ ##
4
+ # The collection of teams that belong to the organization.
5
+ has_many :teams, class_name: 'ESP::Team'
6
+
7
+ ##
8
+ # The collection of sub_organizations that belong to the organization.
9
+ has_many :sub_organizations, class_name: 'ESP::SubOrganization'
10
+
11
+ ##
12
+ # The collection of users that belong to the organization.
13
+ has_many :users, class_name: 'ESP::User'
14
+
15
+ ##
16
+ # The collection of reports that belong to the organization.
17
+ has_many :reports, class_name: 'ESP::Report'
18
+
19
+ ##
20
+ # The collection of external_accounts that belong to the organization.
21
+ has_many :external_accounts, class_name: 'ESP::ExternalAccount'
22
+
23
+ ##
24
+ # The collection of organizations that belong to the organization.
25
+ has_many :custom_signatures, class_name: 'ESP::CustomSignature'
26
+
27
+ # Not Implemented. You cannot create an Organization.
28
+ def create # :nodoc:
29
+ fail ESP::NotImplementedError
30
+ end
31
+
32
+ # Not Implemented. You cannot destroy an Organization.
33
+ def destroy
34
+ fail ESP::NotImplementedError
35
+ end
36
+
37
+ ##
38
+ # :singleton-method: find
39
+ # Find a Organization by id
40
+ #
41
+ # ==== Parameter
42
+ #
43
+ # +id+ | Required | The ID of the organization to retrieve
44
+ #
45
+ # :call-seq:
46
+ # find(id)
47
+
48
+ # :singleton-method: all
49
+ # Return a paginated Organization list
50
+
51
+ # :singleton-method: create
52
+ # Not Implemented. You cannot create an Organization.
53
+
54
+ # :method: save
55
+ # Update an Organization.
56
+ #
57
+ # ==== Valid Attributes
58
+ #
59
+ # +name+ | Not Required | The new name of the organization
60
+ end
61
+ end
@@ -0,0 +1,46 @@
1
+ module ESP
2
+ class Region < ESP::Resource
3
+ # Not Implemented. You cannot create or update a CloudTrailEvent.
4
+ def save
5
+ fail ESP::NotImplementedError
6
+ end
7
+
8
+ # Not Implemented. You cannot destroy a an CloudTrailEvent.
9
+ def destroy
10
+ fail ESP::NotImplementedError
11
+ end
12
+
13
+ # Create a suppression for this region.
14
+ #
15
+ # ==== Parameter
16
+ #
17
+ # +arguments+ | Required | A hash of region suppression attributes
18
+ #
19
+ # ===== Valid Arguments
20
+ #
21
+ # +external_account_ids+ | Required | An Array of the external accounts identified by +external_account_id+ to suppress the signature or custom signature on.
22
+ #
23
+ # +reason+ | Required | The reason for creating the suppression.
24
+ #
25
+ # ==== Example
26
+ # suppress(external_account_ids: [5], reason: 'My very good reason for creating this suppression')
27
+ def suppress(arguments = {})
28
+ arguments = arguments.with_indifferent_access
29
+ ESP::Suppression::Region.create(regions: [code], external_account_ids: Array(arguments[:external_account_ids]), reason: arguments[:reason])
30
+ end
31
+
32
+ ##
33
+ # :singleton-method: find
34
+ # Find a Region by id
35
+ #
36
+ # ==== Parameter
37
+ #
38
+ # +id+ | Required | The ID of the region to retrieve
39
+ #
40
+ # :call-seq:
41
+ # find(id)
42
+
43
+ # :singleton-method: all
44
+ # Return a paginated Region list
45
+ end
46
+ end
@@ -0,0 +1,100 @@
1
+ module ESP
2
+ class Report < ESP::Resource
3
+ ##
4
+ # The organization the report belongs to.
5
+ belongs_to :organization, class_name: 'ESP::Organization'
6
+
7
+ ##
8
+ # The sub_organization the report belongs to.
9
+ belongs_to :sub_organization, class_name: 'ESP::SubOrganization'
10
+
11
+ ##
12
+ # The team the report belongs to.
13
+ belongs_to :team, class_name: 'ESP::Team'
14
+
15
+ # Not Implemented. You cannot create or update a Report.
16
+ def update
17
+ fail ESP::NotImplementedError
18
+ end
19
+
20
+ # Not Implemented. You cannot destroy a Report.
21
+ def destroy
22
+ fail ESP::NotImplementedError
23
+ end
24
+
25
+ # Enqueue a report to be run for the given team.
26
+ # Returns a Report object with a status of 'queued' and an id
27
+ # ==== Attribute
28
+ #
29
+ # +team_id+ | Required | The ID of the team to create a report for
30
+ #
31
+ # Periodically check the API
32
+ # ESP::Report.find(<id>)
33
+ # until status is 'complete'.
34
+ #
35
+ # If not successful, returns a Report object with the errors object populated.
36
+ def self.create(arguments = {})
37
+ fail ArgumentError, "You must supply a team id." unless arguments.with_indifferent_access[:team_id].present?
38
+ super
39
+ rescue ActiveResource::ResourceNotFound => error
40
+ new(arguments).tap { |r| r.load_remote_errors(error, true) }
41
+ end
42
+
43
+ # Returns a paginated collection of alerts for the report
44
+ #
45
+ # ==== Parameters
46
+ #
47
+ # +arguments+ | Not Required | An optional hash of search criteria to filter the returned collection
48
+ #
49
+ # ===== Valid Arguments
50
+ #
51
+ # +region_id+ | Not Required | Return only alerts for this region.
52
+ #
53
+ # +status+ | Not Required | Return only alerts for the give status(es). Valid values are fail, warn, error, pass, info
54
+ #
55
+ # +first_seen+ | Not Required | Return only alerts that have started within a number of hours of the report. For example, first_seen of 3 will return alerts that started showing up within the last 3 hours of the report.
56
+ #
57
+ # +suppressed+ | Not Required | Return only suppressed alerts
58
+ #
59
+ # +team_id+ | Not Required | Return only alerts for the given team.
60
+ #
61
+ # +external_account_id+ | Not Required | Return only alerts for the given external id.
62
+ #
63
+ # +service_id+ | Not Required | Return only alerts on signatures with the given service.
64
+ #
65
+ # +signature_severity+ | Not Required | Return only alerts for signatures with the given risk_level. Valid values are Low, Medium, High
66
+ #
67
+ # +signature_name+ | Not Required | Return only alerts for signatures with the given name.
68
+ #
69
+ # +resource+ | Not Required | Return only alerts for the given resource or tag.
70
+ #
71
+ # +signature_identifier+ | Not Required | Return only alerts for signatures with the given identifier.
72
+ #
73
+ # ==== Example
74
+ #
75
+ # report = ESP::Report.find(345)
76
+ # alerts = report.alerts(status: 'fail', signature_severity: 'High')
77
+ def alerts(arguments = {})
78
+ ESP::Alert.for_report(id, arguments)
79
+ end
80
+
81
+ # Returns the stats for this report
82
+ def stat
83
+ ESP::Stat.for_report(id)
84
+ end
85
+
86
+ ##
87
+ # :singleton-method: find
88
+ # Find a Report by id
89
+ #
90
+ # ==== Parameter
91
+ #
92
+ # +id+ | Required | The ID of the report to retrieve
93
+ #
94
+ # :call-seq:
95
+ # find(id)
96
+
97
+ # :singleton-method: all
98
+ # Return a paginated Report list
99
+ end
100
+ end