emasser 3.12.0 → 3.22.0
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.
- checksums.yaml +4 -4
- data/.env-example +18 -12
- data/.github/workflows/anchore-syft.yml +38 -0
- data/.github/workflows/codeql-analysis.yml +2 -2
- data/.github/workflows/push-to-docker-mail.yml +1 -2
- data/.github/workflows/push-to-docker.yml +2 -2
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/test-cli.yml +4 -4
- data/.mergify.yml +11 -11
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/Dockerfile +6 -4
- data/Gemfile.lock +108 -64
- data/README.md +7 -7
- data/docs/features.md +492 -524
- data/emasser.gemspec +19 -13
- data/images/emasser_architecture.png +0 -0
- data/lib/emasser/configuration.rb +136 -35
- data/lib/emasser/constants.rb +4 -0
- data/lib/emasser/delete.rb +75 -7
- data/lib/emasser/errors.rb +9 -0
- data/lib/emasser/get.rb +610 -177
- data/lib/emasser/help/approvalCac_post_mapper.md +6 -5
- data/lib/emasser/help/approvalPac_post_mapper.md +1 -5
- data/lib/emasser/help/artifacts_del_mapper.md +2 -2
- data/lib/emasser/help/artifacts_post_mapper.md +23 -34
- data/lib/emasser/help/artifacts_put_mapper.md +28 -9
- data/lib/emasser/help/cloudresource_post_mapper.md +4 -3
- data/lib/emasser/help/controls_put_mapper.md +24 -16
- data/lib/emasser/help/hardware_post_mapper.md +41 -0
- data/lib/emasser/help/hardware_put_mapper.md +42 -0
- data/lib/emasser/help/milestone_del_mapper.md +1 -1
- data/lib/emasser/help/milestone_post_mapper.md +3 -1
- data/lib/emasser/help/milestone_put_mapper.md +1 -8
- data/lib/emasser/help/poam_del_mapper.md +1 -1
- data/lib/emasser/help/poam_post_mapper.md +40 -14
- data/lib/emasser/help/poam_put_mapper.md +43 -18
- data/lib/emasser/help/software_post_mapper.md +59 -0
- data/lib/emasser/help/software_put_mapper.md +60 -0
- data/lib/emasser/help/staticcode_post_mapper.md +0 -4
- data/lib/emasser/help/testresults_post_mapper.md +8 -11
- data/lib/emasser/output_converters.rb +50 -42
- data/lib/emasser/post.rb +603 -231
- data/lib/emasser/put.rb +453 -193
- data/lib/emasser/version.rb +1 -1
- metadata +51 -33
- data/images/emasser_architecture.jpg +0 -0
- data/images/emasser_diagram-Page-3.jpg +0 -0
data/lib/emasser/post.rb
CHANGED
@@ -24,7 +24,7 @@ class SubCommandBase < Thor
|
|
24
24
|
# rubocop:enable Style/OptionalBooleanParameter
|
25
25
|
end
|
26
26
|
|
27
|
-
# Override thor's long_desc
|
27
|
+
# Override thor's long_desc indentation behavior
|
28
28
|
class Thor
|
29
29
|
module Shell
|
30
30
|
class Basic
|
@@ -44,7 +44,7 @@ module Emasser
|
|
44
44
|
# The Registration endpoint provides the ability to register a certificate & obtain an API-key.
|
45
45
|
#
|
46
46
|
# Endpoint:
|
47
|
-
# /api/api-key
|
47
|
+
# /api/api-key
|
48
48
|
class Register < SubCommandBase
|
49
49
|
def self.exit_on_failure?
|
50
50
|
true
|
@@ -54,11 +54,11 @@ module Emasser
|
|
54
54
|
# rubocop:disable Style/RedundantBegin
|
55
55
|
def cert
|
56
56
|
begin
|
57
|
-
result = EmassClient::RegistrationApi.new.register_user(
|
57
|
+
result = EmassClient::RegistrationApi.new.register_user(Emasser::GET_REGISTER_RETURN_TYPE)
|
58
58
|
puts to_output_hash(result).green
|
59
59
|
rescue EmassClient::ApiError => e
|
60
60
|
puts 'Exception when calling RegistrationApi->register_user'.red
|
61
|
-
puts to_output_hash(e)
|
61
|
+
puts to_output_hash(e).split('\n').join('. ')
|
62
62
|
end
|
63
63
|
end
|
64
64
|
# rubocop:enable Style/RedundantBegin
|
@@ -68,7 +68,7 @@ module Emasser
|
|
68
68
|
# system's Assessment Procedures (CCIs) which determine Security Control compliance.
|
69
69
|
#
|
70
70
|
# Endpoint:
|
71
|
-
# /api/systems/{systemId}/test-results
|
71
|
+
# /api/systems/{systemId}/test-results
|
72
72
|
class TestResults < SubCommandBase
|
73
73
|
def self.exit_on_failure?
|
74
74
|
true
|
@@ -78,17 +78,17 @@ module Emasser
|
|
78
78
|
long_desc Help.text(:testresults_post_mapper)
|
79
79
|
|
80
80
|
# Required fields
|
81
|
-
option :systemId, type: :numeric, required: true,
|
81
|
+
option :systemId, aliases: '-s', type: :numeric, required: true,
|
82
82
|
desc: 'A numeric value representing the system identification'
|
83
|
-
option :
|
84
|
-
option :testedBy,
|
85
|
-
option :testDate,
|
86
|
-
option :description,
|
87
|
-
option :complianceStatus,
|
83
|
+
option :assessmentProcedure, type: :string, required: true, desc: 'The Security Control Assessment Procedure being assessed'
|
84
|
+
option :testedBy, type: :string, required: true, desc: 'The person that conducted the test (Last Name, First)'
|
85
|
+
option :testDate, type: :numeric, required: true, desc: 'The date test was conducted, Unix time format.'
|
86
|
+
option :description, type: :string, required: true, desc: 'The description of test result. 4000 Characters.'
|
87
|
+
option :complianceStatus, type: :string, required: true, enum: ['Compliant', 'Non-Compliant', 'Not Applicable']
|
88
88
|
|
89
89
|
def add
|
90
90
|
body = EmassClient::TestResultsGet.new
|
91
|
-
body.
|
91
|
+
body.assessment_procedure = options[:assessmentProcedure]
|
92
92
|
body.tested_by = options[:testedBy]
|
93
93
|
body.test_date = options[:testDate]
|
94
94
|
body.description = options[:description]
|
@@ -111,7 +111,7 @@ module Emasser
|
|
111
111
|
# items to a system.
|
112
112
|
#
|
113
113
|
# Endpoint:
|
114
|
-
# /api/systems/{systemId}/poams
|
114
|
+
# /api/systems/{systemId}/poams
|
115
115
|
class Poams < SubCommandBase
|
116
116
|
def self.exit_on_failure?
|
117
117
|
true
|
@@ -128,7 +128,6 @@ module Emasser
|
|
128
128
|
# completionDate, milestones (at least 1)
|
129
129
|
# Not Applicable POAM can not be created
|
130
130
|
#--------------------------------------------------------------------------
|
131
|
-
#
|
132
131
|
# If a POC email is supplied, the application will attempt to locate a user
|
133
132
|
# already registered within the application and pre-populate any information
|
134
133
|
# not explicitly supplied in the request. If no such user is found, these
|
@@ -139,76 +138,135 @@ module Emasser
|
|
139
138
|
long_desc Help.text(:poam_post_mapper)
|
140
139
|
|
141
140
|
# Required parameters/fields (the poamId and displayPoamId are generated by the PUT call)
|
142
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
143
|
-
option :status, type: :string, required: true, enum: ['Ongoing', 'Risk Accepted', 'Completed', 'Not Applicable']
|
141
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
142
|
+
option :status, type: :string, required: true, enum: ['Ongoing', 'Risk Accepted', 'Completed', 'Not Applicable', 'Archived']
|
144
143
|
option :vulnerabilityDescription, type: :string, required: true, desc: 'POA&M vulnerability description'
|
145
|
-
option :
|
144
|
+
option :sourceIdentifyingVulnerability,
|
146
145
|
type: :string, required: true, desc: 'Source that identifies the vulnerability'
|
147
146
|
option :pocOrganization, type: :string, required: true, desc: 'Organization/Office represented'
|
148
147
|
option :resources, type: :string, required: true, desc: 'List of resources used'
|
149
148
|
|
149
|
+
# Some eMASS instances also require the Risk Analysis fields
|
150
|
+
# Note: These are grouped here for identification only, they are not marked as required.
|
151
|
+
option :severity, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
152
|
+
option :relevanceOfThreat, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
153
|
+
option :likelihood, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
154
|
+
option :impact, type: :string, required: false, desc: 'Description of Security Control’s impact'
|
155
|
+
option :residualRiskLevel, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
156
|
+
option :mitigations, type: :string, required: false, desc: 'Mitigations explanation'
|
157
|
+
|
150
158
|
# Conditional parameters/fields
|
151
159
|
option :milestone, type: :hash, required: false, desc: 'key:values are: description and scheduledCompletionDate'
|
152
160
|
option :pocFirstName, type: :string, required: false, desc: 'First name of POC'
|
153
161
|
option :pocLastName, type: :string, required: false, desc: 'Last name of POC.'
|
154
162
|
option :pocEmail, type: :string, required: false, desc: 'Email address of POC'
|
155
163
|
option :pocPhoneNumber, type: :string, required: false, desc: 'Phone number of POC (area code) ***-**** format'
|
156
|
-
option :severity, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
164
|
+
# option :severity, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
157
165
|
option :scheduledCompletionDate,
|
158
166
|
type: :numeric, required: false, desc: 'The scheduled completion date - Unix time format'
|
159
167
|
option :completionDate,
|
160
168
|
type: :numeric, required: false, desc: 'The schedule completion date - Unix time format'
|
161
169
|
option :comments, type: :string, required: false, desc: 'Comments for completed and risk accepted POA&M items'
|
170
|
+
# The next fields are Required for VA. Optional for Army and USCG.
|
171
|
+
option :personnelResourcesFundedBaseHours, type: :numeric, required: false, desc: 'Funded based hours (125.34)'
|
172
|
+
option :personnelResourcesCostCode, type: :string, required: false, desc: 'Values are specific per eMASS instance'
|
173
|
+
option :personnelResourcesUnfundedBaseHours, type: :numeric, required: false, desc: 'Funded based hours (100.00)'
|
174
|
+
option :personnelResourcesNonfundingObstacle, type: :string, required: false, desc: 'Values are specific per eMASS instance'
|
175
|
+
option :personnelResourcesNonfundingObstacleOtherReason, type: :string, required: false, desc: 'Reason (text 2,000 char)'
|
176
|
+
option :nonPersonnelResourcesFundedAmount, type: :numeric, required: false, desc: 'Funded based hours (100.00)'
|
177
|
+
option :nonPersonnelResourcesCostCode, type: :string, required: false, desc: 'Values are specific per eMASS instance'
|
178
|
+
option :nonPersonnelResourcesUnfundedAmount, type: :numeric, required: false, desc: 'Funded based hours (100.00)'
|
179
|
+
option :nonPersonnelResourcesNonfundingObstacle, type: :string, required: false, desc: 'Values are specific per eMASS instance'
|
180
|
+
option :nonPersonnelResourcesNonfundingObstacleOtherReason, type: :string, required: false, desc: 'Reason (text 2,000 char)'
|
162
181
|
|
163
182
|
# Optional parameters/fields
|
164
183
|
option :externalUid, type: :string, required: false, desc: 'External ID associated with the POA&M'
|
165
184
|
option :controlAcronym, type: :string, required: false, desc: 'The system acronym(s) e.g "AC-1, AC-2"'
|
166
|
-
option :
|
185
|
+
option :assessmentProcedure, type: :string, required: false, desc: 'The system CCIS string numerical value'
|
167
186
|
option :securityChecks, type: :string, required: false, desc: 'Security Checks that are associated with the POA&M'
|
168
187
|
option :rawSeverity, type: :string, required: false, enum: %w[I II III]
|
169
|
-
option :relevanceOfThreat,
|
170
|
-
|
171
|
-
option :
|
172
|
-
option :impact, type: :string, required: false, desc: 'Description of Security Control’s impact'
|
188
|
+
# option :relevanceOfThreat, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
189
|
+
# option :likelihood, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
190
|
+
# option :impact, type: :string, required: false, desc: 'Description of Security Control’s impact'
|
173
191
|
option :impactDescription, type: :string, required: false, desc: 'Description of the security control impact'
|
174
|
-
option :residualRiskLevel,
|
175
|
-
|
176
|
-
option :
|
177
|
-
|
178
|
-
|
179
|
-
#
|
192
|
+
# option :residualRiskLevel, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
193
|
+
option :recommendations, type: :string, required: false, desc: 'Recommendations'
|
194
|
+
# option :mitigations, type: :string, required: false, desc: 'Mitigation explanation'
|
195
|
+
# The next field is Required for VA. Optional for Army and USCG.
|
196
|
+
option :identifiedInCFOAuditOrOtherReview, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
|
197
|
+
# The next fields are for Navy Only
|
198
|
+
option :resultingResidualRiskLevelAfterProposedMitigations, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
199
|
+
option :predisposingConditions, type: :string, required: false, desc: 'Conditions (text 2,000 char)'
|
200
|
+
option :threatDescription, type: :string, required: false, desc: 'Threat description (text 2,000 char)'
|
201
|
+
option :devicesAffected, type: :string, required: false, desc: 'devicesAffected'
|
202
|
+
|
203
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
180
204
|
def add
|
181
|
-
#
|
182
|
-
|
183
|
-
body.status = options[:status]
|
184
|
-
body.vulnerability_description = options[:vulnerabilityDescription]
|
185
|
-
body.source_ident_vuln = options[:sourceIdentVuln]
|
186
|
-
body.poc_organization = options[:pocOrganization]
|
187
|
-
body.resources = options[:resources]
|
205
|
+
# Check if business logic is satisfied
|
206
|
+
process_business_logic
|
188
207
|
|
189
|
-
|
208
|
+
# Required fields
|
209
|
+
require_fields = EmassClient::PoamRequiredFields.new
|
210
|
+
require_fields.status = options[:status]
|
211
|
+
require_fields.vulnerability_description = options[:vulnerabilityDescription]
|
212
|
+
require_fields.source_identifying_vulnerability = options[:sourceIdentifyingVulnerability]
|
213
|
+
require_fields.poc_organization = options[:pocOrganization]
|
214
|
+
require_fields.resources = options[:resources]
|
215
|
+
# Required for VA, optional for Army and USCG. - defaults to false
|
216
|
+
require_fields.identified_in_cfo_audit_or_other_review = options[:identifiedInCFOAuditOrOtherReview] if options[:identifiedInCFOAuditOrOtherReview]
|
190
217
|
|
191
218
|
# Add conditional fields
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
219
|
+
conditional_fields = EmassClient::PoamConditionalFields.new
|
220
|
+
conditional_fields.poc_first_name = options[:pocFirstName] if options[:pocFirstName]
|
221
|
+
conditional_fields.poc_last_name = options[:pocLastName] if options[:pocLastName]
|
222
|
+
conditional_fields.poc_email = options[:pocEmail] if options[:pocEmail]
|
223
|
+
conditional_fields.poc_phone_number = options[:pocPhoneNumber] if options[:pocPhoneNumber]
|
224
|
+
conditional_fields.severity = options[:severity] if options[:severity]
|
225
|
+
conditional_fields.scheduled_completion_date = options[:scheduledCompletionDate] if options[:scheduledCompletionDate]
|
226
|
+
conditional_fields.completion_date = options[:completionDate] if options[:completionDate]
|
227
|
+
conditional_fields.comments = options[:comments] if options[:comments]
|
228
|
+
conditional_fields.personnel_resources_funded_base_hours = options[:personnelResourcesFundedBaseHours] if options[:personnelResourcesFundedBaseHours]
|
229
|
+
conditional_fields.personnel_resources_cost_code = options[:personnelResourcesCostCode] if options[:personnelResourcesCostCode]
|
230
|
+
conditional_fields.personnel_resources_unfunded_base_hours = options[:personnelResourcesUnfundedBaseHours] if options[:personnelResourcesUnfundedBaseHours]
|
231
|
+
conditional_fields.personnel_resources_nonfunding_obstacle = options[:personnelResourcesNonfundingObstacle] if options[:personnelResourcesNonfundingObstacle]
|
232
|
+
conditional_fields.personnel_resources_nonfunding_obstacle_other_reason = options[:personnelResourcesNonfundingObstacleOtherReason] if options[:personnelResourcesNonfundingObstacleOtherReason]
|
233
|
+
conditional_fields.non_personnel_resources_funded_amount = options[:nonPersonnelResourcesFundedAmount] if options[:nonPersonnelResourcesFundedAmount]
|
234
|
+
conditional_fields.non_personnel_resources_cost_code = options[:nonPersonnelResourcesCostCode] if options[:nonPersonnelResourcesCostCode]
|
235
|
+
conditional_fields.non_personnel_resources_unfunded_amount = options[:nonPersonnelResourcesUnfundedAmount] if options[:nonPersonnelResourcesUnfundedAmount]
|
236
|
+
conditional_fields.non_personnel_resources_nonfunding_obstacle = options[:nonPersonnelResourcesNonfundingObstacle] if options[:nonPersonnelResourcesNonfundingObstacle]
|
237
|
+
conditional_fields.non_personnel_resources_nonfunding_obstacle_other_reason = options[:nonPersonnelResourcesNonfundingObstacleOtherReason] if options[:nonPersonnelResourcesNonfundingObstacleOtherReason]
|
197
238
|
|
198
239
|
# Add optional fields
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
240
|
+
optional_fields = EmassClient::PoamOptionalFields.new
|
241
|
+
optional_fields.external_uid = options[:externalUid] if options[:externalUid]
|
242
|
+
optional_fields.control_acronym = options[:controlAcronym] if options[:controlAcronym]
|
243
|
+
optional_fields.assessment_procedure = options[:assessmentProcedure] if options[:assessmentProcedure]
|
244
|
+
optional_fields.security_checks = options[:securityChecks] if options[:securityChecks]
|
245
|
+
optional_fields.raw_severity = options[:rawSeverity] if options[:rawSeverity]
|
246
|
+
optional_fields.relevance_of_threat = options[:relevanceOfThreat] if options[:relevanceOfThreat]
|
247
|
+
optional_fields.likelihood = options[:likelihood] if options[:likelihood]
|
248
|
+
optional_fields.impact = options[:impact] if options[:impact]
|
249
|
+
optional_fields.impact_description = options[:impactDescription] if options[:impactDescription]
|
250
|
+
optional_fields.residual_risk_level = options[:residualRiskLevel] if options[:residualRiskLevel]
|
251
|
+
optional_fields.recommendations = options[:recommendations] if options[:recommendations]
|
252
|
+
optional_fields.mitigations = options[:mitigations] if options[:mitigations]
|
253
|
+
optional_fields.resulting_residual_risk_level_after_proposed_mitigations = options[:resultingResidualRiskLevelAfterProposedMitigations] if options[:resultingResidualRiskLevelAfterProposedMitigations]
|
254
|
+
optional_fields.predisposing_conditions = options[:predisposingConditions] if options[:predisposingConditions]
|
255
|
+
optional_fields.threat_description = options[:threatDescription] if options[:threatDescription]
|
256
|
+
optional_fields.devices_affected = options[:devicesAffected] if options[:devicesAffected]
|
257
|
+
|
258
|
+
# Build the milestones object array
|
259
|
+
milestone = {}
|
260
|
+
milestone['description'] = options[:milestone]['description'] if options[:milestone]['description']
|
261
|
+
milestone['scheduledCompletionDate'] = options[:milestone]['scheduledCompletionDate'].to_f if options[:milestone]['scheduledCompletionDate']
|
262
|
+
milestone_array = Array.new(1, milestone)
|
263
|
+
|
264
|
+
# Build the request body
|
265
|
+
body = {}
|
266
|
+
body = body.merge(require_fields)
|
267
|
+
body = body.merge(optional_fields)
|
268
|
+
body = body.merge(conditional_fields)
|
269
|
+
body = body.merge({ milestones: milestone_array })
|
212
270
|
body_array = Array.new(1, body)
|
213
271
|
|
214
272
|
begin
|
@@ -219,11 +277,11 @@ module Emasser
|
|
219
277
|
puts to_output_hash(e)
|
220
278
|
end
|
221
279
|
end
|
222
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
280
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
223
281
|
|
224
|
-
# rubocop:disable Metrics/BlockLength, Metrics/
|
282
|
+
# rubocop:disable Metrics/BlockLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
225
283
|
no_commands do
|
226
|
-
def process_business_logic
|
284
|
+
def process_business_logic
|
227
285
|
#-----------------------------------------------------------------------------
|
228
286
|
# Conditional fields based on the status field values
|
229
287
|
# "Risk Accepted" comments, resources
|
@@ -244,8 +302,6 @@ module Emasser
|
|
244
302
|
puts ' scheduledCompletionDate, or milestone'.red
|
245
303
|
puts POAMS_PUT_HELP_MESSAGE.yellow
|
246
304
|
exit
|
247
|
-
else
|
248
|
-
body.comments = options[:comments]
|
249
305
|
end
|
250
306
|
elsif options[:status] == "Ongoing"
|
251
307
|
if options[:scheduledCompletionDate].nil? || options[:milestone].nil?
|
@@ -255,17 +311,14 @@ module Emasser
|
|
255
311
|
puts POAMS_POST_HELP_MESSAGE.yellow
|
256
312
|
exit
|
257
313
|
elsif options[:milestone]["description"].nil? || options[:milestone]["scheduledCompletionDate"].nil?
|
258
|
-
puts 'Missing
|
314
|
+
puts 'Missing milestone parameters/fields'.red
|
259
315
|
print_milestone_help
|
260
316
|
exit
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
milestone.scheduled_completion_date = options[:milestone]["scheduledCompletionDate"]
|
267
|
-
milestone_array = Array.new(1, milestone)
|
268
|
-
body.milestones = milestone_array
|
317
|
+
elsif options[:severity].nil? || options[:relevanceOfThreat].nil? ||
|
318
|
+
options[:likelihood].nil? || options[:impact].nil? ||
|
319
|
+
options[:residualRiskLevel].nil? || options[:mitigation].nil?
|
320
|
+
puts 'Certain eMASS instances also require the Risk Analysis fields to be populated:'.yellow
|
321
|
+
puts ' Severity, Relevance of Threat, Likelihood, Impact, Residual Risk Level, and Mitigations'.yellow
|
269
322
|
end
|
270
323
|
elsif options[:status] == "Completed"
|
271
324
|
if options[:scheduledCompletionDate].nil? || options[:comments].nil? ||
|
@@ -275,16 +328,6 @@ module Emasser
|
|
275
328
|
print_milestone_help
|
276
329
|
puts POAMS_POST_HELP_MESSAGE.yellow
|
277
330
|
exit
|
278
|
-
else
|
279
|
-
body.scheduled_completion_date = options[:scheduledCompletionDate]
|
280
|
-
body.comments = options[:comments]
|
281
|
-
body.completion_date = options[:completionDate]
|
282
|
-
|
283
|
-
milestone = EmassClient::MilestonesRequiredPost.new
|
284
|
-
milestone.description = options[:milestone]["description"]
|
285
|
-
milestone.scheduled_completion_date = options[:milestone]["scheduledCompletionDate"]
|
286
|
-
milestone_array = Array.new(1, milestone)
|
287
|
-
body.milestones = milestone_array
|
288
331
|
end
|
289
332
|
end
|
290
333
|
|
@@ -326,14 +369,14 @@ module Emasser
|
|
326
369
|
puts ' --milestone description:"[value]" scheduledCompletionDate:"[value]"'.yellow
|
327
370
|
end
|
328
371
|
end
|
329
|
-
# rubocop:enable Metrics/BlockLength, Metrics/
|
372
|
+
# rubocop:enable Metrics/BlockLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
330
373
|
end
|
331
374
|
|
332
375
|
# The Milestones endpoints provide the ability add milestones that are associated with
|
333
376
|
# Plan of Action and Milestones (POA&M) items for a system.
|
334
377
|
#
|
335
378
|
# Endpoint:
|
336
|
-
# /api/systems/{systemId}/poams/{poamId}/milestones
|
379
|
+
# /api/systems/{systemId}/poams/{poamId}/milestones
|
337
380
|
class Milestones < SubCommandBase
|
338
381
|
def self.exit_on_failure?
|
339
382
|
true
|
@@ -343,11 +386,10 @@ module Emasser
|
|
343
386
|
long_desc Help.text(:milestone_post_mapper)
|
344
387
|
|
345
388
|
# Required parameters/fields
|
346
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
347
|
-
option :poamId, type: :numeric, required: true, desc: 'A numeric value representing the poam identification'
|
348
|
-
option :description, type: :string,
|
349
|
-
option :scheduledCompletionDate,
|
350
|
-
type: :numeric, required: true, desc: 'The scheduled completion date - Unix time format'
|
389
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
390
|
+
option :poamId, aliases: '-p', type: :numeric, required: true, desc: 'A numeric value representing the poam identification'
|
391
|
+
option :description, aliases: '-d', type: :string, required: true, desc: 'The milestone description'
|
392
|
+
option :scheduledCompletionDate, aliases: '-c', type: :numeric, required: true, desc: 'The scheduled completion date - Unix time format'
|
351
393
|
|
352
394
|
def add
|
353
395
|
body = EmassClient::MilestonesGet.new
|
@@ -366,10 +408,17 @@ module Emasser
|
|
366
408
|
end
|
367
409
|
end
|
368
410
|
|
369
|
-
# Add one or many artifacts for a system (delivery method
|
411
|
+
# Add one or many artifacts for a system (delivery method can be a file or a zip file)
|
412
|
+
# Two Artifact POST methods are currently accepted: individual and bulk.
|
413
|
+
# Filename uniqueness within an eMASS system will be enforced by the API for both methods.
|
370
414
|
#
|
371
|
-
#
|
372
|
-
#
|
415
|
+
# This method handles the upload of one or more files to the eMASS system.
|
416
|
+
# If a single file is provided (could be a file or zip file) the file is open (File.open)
|
417
|
+
# and passed to the API.
|
418
|
+
# It multiple files are provided, they are zipped into a single archive and sent to the API
|
419
|
+
#
|
420
|
+
# Endpoint:
|
421
|
+
# /api/systems/{systemId}/artifacts
|
373
422
|
class Artifacts < SubCommandBase
|
374
423
|
def self.exit_on_failure?
|
375
424
|
true
|
@@ -379,50 +428,58 @@ module Emasser
|
|
379
428
|
long_desc Help.text(:artifacts_post_mapper)
|
380
429
|
|
381
430
|
# Required parameters/fields
|
382
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
383
|
-
option :files, type: :array, required: true, desc: 'Artifact file(s) to post to the given system'
|
384
|
-
option :type,
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
option :
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
option :
|
393
|
-
option :refPageNumber, type: :string, required: false, desc: 'Artifact reference page number'
|
394
|
-
option :ccis, type: :string, required: false, desc: 'The system CCIs string numerical value'
|
395
|
-
option :controls,
|
396
|
-
type: :string, required: false,
|
397
|
-
desc: 'Control acronym associated with the artifact. NIST SP 800-53 Revision 4 defined'
|
398
|
-
option :artifactExpirationDate,
|
399
|
-
type: :numeric, required: false, desc: 'Date Artifact expires and requires review - Unix time format'
|
400
|
-
option :lastReviewedDate,
|
401
|
-
type: :numeric, required: false, desc: 'Date Artifact was last reviewed - Unix time format'
|
431
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
432
|
+
option :files, aliases: '-f', type: :array, required: true, desc: 'Artifact file(s) to post to the given system'
|
433
|
+
option :isBulk, aliases: '-B', type: :boolean, require: true, default: false, desc: 'Set to false for single file upload, true for multiple file upload (expects a .zip file)'
|
434
|
+
|
435
|
+
# Optional parameters/fields - if not provided, default values are used
|
436
|
+
# These are the only options the backend will accept, all others are ignored
|
437
|
+
option :type, aliases: '-t', type: :string, required: false, default: 'Other',
|
438
|
+
desc: 'The type of artifact. Possible values are: Procedure, Diagram, Policy, Labor, Document, Image, Other, Scan Result, Auditor Report. May also accept other values set by system administrators.'
|
439
|
+
option :category, aliases: '-c', type: :string, required: false, default: 'Evidence',
|
440
|
+
desc: 'The category of artifact. Possible values are: Implementation Guidance, Evidence. May also accept other values set by system administrators.'
|
441
|
+
option :isTemplate, aliases: '-T', type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
|
402
442
|
|
403
443
|
def upload
|
404
444
|
optional_options_keys = optional_options(@_initializer).keys
|
405
445
|
optional_options = to_input_hash(optional_options_keys, options)
|
406
|
-
# Remove
|
407
|
-
optional_options.delete(:
|
446
|
+
# Remove isBulk as it is an options parameter sent to the API.
|
447
|
+
optional_options.delete(:is_bulk)
|
408
448
|
|
449
|
+
# Options contain the default values (type, category, and isTemplate)
|
450
|
+
# They are sent to the API in the form_params option
|
409
451
|
opts = {}
|
410
|
-
opts[:
|
411
|
-
opts[:category] = options[:category]
|
412
|
-
opts[:is_template] = options[:is_template]
|
452
|
+
opts[:is_bulk] = options[:isBulk]
|
413
453
|
opts[:form_params] = optional_options
|
414
454
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
455
|
+
# Configure the upload file(s)
|
456
|
+
remove_temp_file = false
|
457
|
+
begin
|
458
|
+
# If we have a single file, could be a zip file
|
459
|
+
if options[:files].length == 1
|
460
|
+
tempfile = File.open(options[:files][0], 'r')
|
461
|
+
# if we have multiple files zip them into a zip file
|
462
|
+
elsif options[:files].length > 1
|
463
|
+
remove_temp_file = true
|
464
|
+
tempfile = Tempfile.create(['artifacts', '.zip'])
|
465
|
+
|
466
|
+
Zip::OutputStream.open(tempfile.path) do |z|
|
467
|
+
options[:files].each do |file|
|
468
|
+
# Add file name to the archive: Don't use the full path
|
469
|
+
z.put_next_entry(File.basename(file))
|
470
|
+
# Add the file to the archive
|
471
|
+
z.print File.read(file)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
else
|
475
|
+
puts 'No file(s) provided!'.yellow
|
423
476
|
end
|
477
|
+
rescue Errno::ENOENT => e
|
478
|
+
warn "File open exception: #{e}".red
|
479
|
+
exit 1
|
424
480
|
end
|
425
481
|
|
482
|
+
# Call the API
|
426
483
|
begin
|
427
484
|
result = EmassClient::ArtifactsApi
|
428
485
|
.new
|
@@ -432,9 +489,10 @@ module Emasser
|
|
432
489
|
puts 'Exception when calling ArtifactsApi->add_artifacts_by_system_id'.red
|
433
490
|
puts to_output_hash(e)
|
434
491
|
ensure
|
492
|
+
# Close the file
|
493
|
+
tempfile.close
|
435
494
|
# Delete the temp file
|
436
|
-
|
437
|
-
tempfile.close
|
495
|
+
if remove_temp_file
|
438
496
|
FileUtils.remove_file(tempfile, true)
|
439
497
|
end
|
440
498
|
end
|
@@ -444,7 +502,7 @@ module Emasser
|
|
444
502
|
# Add a Control Approval Chain (CAC)
|
445
503
|
#
|
446
504
|
# Endpoints:
|
447
|
-
# /api/systems/{systemId}/approval/cac
|
505
|
+
# /api/systems/{systemId}/approval/cac
|
448
506
|
class CAC < SubCommandBase
|
449
507
|
def self.exit_on_failure?
|
450
508
|
true
|
@@ -454,11 +512,11 @@ module Emasser
|
|
454
512
|
long_desc Help.text(:approvalCac_post_mapper)
|
455
513
|
|
456
514
|
# Required parameters/fields
|
457
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
458
|
-
option :controlAcronym, type: :string, required: true, desc: 'The system acronym "AC-1, AC-2"'
|
515
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
516
|
+
option :controlAcronym, aliases: '-a', type: :string, required: true, desc: 'The system acronym "AC-1, AC-2"'
|
459
517
|
|
460
518
|
# Conditional parameters/fields
|
461
|
-
option :comments, type: :string, required: false, desc: 'The control approval chain comments'
|
519
|
+
option :comments, aliases: '-c', type: :string, required: false, desc: 'The control approval chain comments'
|
462
520
|
|
463
521
|
def add
|
464
522
|
body = EmassClient::CacGet.new
|
@@ -481,7 +539,7 @@ module Emasser
|
|
481
539
|
# Add a Package Approval Chain (PAC)
|
482
540
|
#
|
483
541
|
# Endpoints:
|
484
|
-
# /api/systems/{systemId}/approval/pac
|
542
|
+
# /api/systems/{systemId}/approval/pac
|
485
543
|
class PAC < SubCommandBase
|
486
544
|
def self.exit_on_failure?
|
487
545
|
true
|
@@ -491,13 +549,10 @@ module Emasser
|
|
491
549
|
long_desc Help.text(:approvalPac_post_mapper)
|
492
550
|
|
493
551
|
# Required parameters/fields
|
494
|
-
option :systemId, type: :numeric, required: true,
|
495
|
-
|
496
|
-
option :
|
497
|
-
|
498
|
-
option :name, type: :string, required: true, desc: 'The control package name'
|
499
|
-
option :comments, type: :string, required: true,
|
500
|
-
desc: 'Comments submitted upon initiation of the indicated workflow'
|
552
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
553
|
+
option :workflow, aliases: '-f', type: :string, required: true, enum: ['Assess and Authorize', 'Assess Only', 'Security Plan Approval']
|
554
|
+
option :name, aliases: '-n', type: :string, required: true, desc: 'The control package name'
|
555
|
+
option :comments, aliases: '-c', type: :string, required: true, desc: 'Comments submitted upon initiation of the indicated workflow'
|
501
556
|
|
502
557
|
def add
|
503
558
|
body = EmassClient::PacGet.new
|
@@ -515,105 +570,300 @@ module Emasser
|
|
515
570
|
end
|
516
571
|
end
|
517
572
|
|
518
|
-
#
|
519
|
-
# scan findings into a system's assets module.
|
520
|
-
#
|
521
|
-
# Application findings can also be cleared from the system.
|
573
|
+
# Add Hardware Baseline assets for a system
|
522
574
|
#
|
523
|
-
#
|
524
|
-
#
|
525
|
-
class
|
575
|
+
# Endpoints:
|
576
|
+
# /api/systems/{systemId}/hw-baseline - Add one or many hardware assets in a system
|
577
|
+
class Hardware < SubCommandBase
|
526
578
|
def self.exit_on_failure?
|
527
579
|
true
|
528
580
|
end
|
529
581
|
|
530
|
-
desc 'add', '
|
531
|
-
long_desc Help.text(:
|
582
|
+
desc 'add', 'Add one or many hardware assets in a system'
|
583
|
+
long_desc Help.text(:hardware_post_mapper)
|
532
584
|
|
533
585
|
# Required parameters/fields
|
534
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
535
|
-
option :
|
536
|
-
|
537
|
-
|
538
|
-
option :
|
539
|
-
option :
|
540
|
-
option :
|
541
|
-
|
542
|
-
|
586
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
587
|
+
option :assetName, aliases: '-a', type: :string, required: true, desc: 'Name of the hardware asset'
|
588
|
+
|
589
|
+
# Conditional fields
|
590
|
+
option :publicFacingFqdn, type: :string, required: false, desc: 'Public facing FQDN. Only applicable if Public Facing is set to true'
|
591
|
+
option :publicFacingIpAddress, type: :string, required: false, desc: 'Public facing IP address. Only applicable if Public Facing is set to true'
|
592
|
+
option :publicFacingUrls, type: :string, required: false, desc: 'Public facing URL(s). Only applicable if Public Facing is set to true'
|
593
|
+
|
594
|
+
# Optional fields
|
595
|
+
option :componentType, type: :string, required: false, desc: 'Component type of the hardware asset'
|
596
|
+
option :nickname, type: :string, required: false, desc: 'Nickname of the hardware asset'
|
597
|
+
option :assetIpAddress, type: :string, required: false, desc: 'IP address of the hardware asset'
|
598
|
+
option :publicFacing, type: :boolean, required: false, desc: 'Public facing is defined as any asset that is accessible from a commercial connection'
|
599
|
+
option :virtualAsset, type: :boolean, required: false, default: false, desc: 'Determine if this is a virtual hardware asset'
|
600
|
+
option :manufacturer, type: :string, required: false, desc: 'Manufacturer of the hardware asset. Populated with “Virtual” by default if Virtual Asset is true'
|
601
|
+
option :modelNumber, type: :string, required: false, desc: 'Model number of the hardware asset. Populated with “Virtual” by default if Virtual Asset is true'
|
602
|
+
option :serialNumber, type: :string, required: false, desc: 'Serial number of the hardware asset. Populated with “Virtual” by default if Virtual Asset is true'
|
603
|
+
option :OsIosFwVersion, type: :string, required: false, desc: 'OS/iOS/FW version of the hardware asset'
|
604
|
+
option :memorySizeType, type: :string, required: false, desc: 'Memory size / type of the hardware asset'
|
605
|
+
option :location, type: :string, required: false, desc: 'Location of the hardware asset'
|
606
|
+
option :approvalStatus, type: :string, required: false, desc: 'Approval status of the hardware asset'
|
607
|
+
option :criticalAsset, type: :boolean, required: false, default: false, desc: 'Indicates whether the asset is a critical information system asset'
|
543
608
|
|
609
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
544
610
|
def add
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
application_findings = EmassClient::StaticCodeApplication.new
|
550
|
-
application_findings.code_check_name = options[:codeCheckName]
|
551
|
-
application_findings.scan_date = options[:scanDate]
|
552
|
-
application_findings.cwe_id = options[:cweId]
|
553
|
-
application_findings.count = options[:count]
|
554
|
-
application_findings.raw_severity = options[:rawSeverity] if options[:rawSeverity]
|
555
|
-
|
556
|
-
app_findings_array = Array.new(1, application_findings)
|
611
|
+
# Required fields
|
612
|
+
require_field = EmassClient::HwBaselineRequiredFields.new
|
613
|
+
require_field.asset_name = options[:assetName]
|
557
614
|
|
558
|
-
|
559
|
-
|
560
|
-
|
615
|
+
# Conditional fields
|
616
|
+
conditional_fields = EmassClient::HwBaselineConditionalFields.new
|
617
|
+
conditional_fields.public_facing_fqdn = options[:publicFacingFqdn] if options[:publicFacingFqdn]
|
618
|
+
conditional_fields.public_facing_ip_address = options[:publicFacingIpAddress] if options[:publicFacingIpAddress]
|
619
|
+
conditional_fields.public_facing_urls = options[:publicFacingUrls] if options[:publicFacingUrls]
|
561
620
|
|
621
|
+
# Optional fields
|
622
|
+
optional_fields = EmassClient::HwBaselineOptionalFields.new
|
623
|
+
optional_fields.component_type = options[:componentType] if options[:componentType]
|
624
|
+
optional_fields.nickname = options[:nickname] if options[:nickname]
|
625
|
+
optional_fields.asset_ip_address = options[:assetIpAddress] if options[:assetIpAddress]
|
626
|
+
optional_fields.public_facing = options[:publicFacing] if options[:publicFacing]
|
627
|
+
optional_fields.virtual_asset = options[:virtualAsset] if options[:virtualAsset]
|
628
|
+
optional_fields.manufacturer = options[:manufacturer] if options[:manufacturer]
|
629
|
+
optional_fields.model_number = options[:modelNumber] if options[:modelNumber]
|
630
|
+
optional_fields.serial_number = options[:serialNumber] if options[:serialNumber]
|
631
|
+
optional_fields.os_ios_fw_version = options[:OsIosFwVersion] if options[:OsIosFwVersion]
|
632
|
+
optional_fields.memory_size_type = options[:memorySizeType] if options[:memorySizeType]
|
633
|
+
optional_fields.location = options[:location] if options[:location]
|
634
|
+
optional_fields.approval_status = options[:approvalStatus] if options[:approvalStatus]
|
635
|
+
optional_fields.critical_asset = options[:criticalAsset] if options[:criticalAsset]
|
636
|
+
|
637
|
+
# Build the body array
|
638
|
+
body = {}
|
639
|
+
body = body.merge(require_field)
|
640
|
+
body = body.merge(conditional_fields)
|
641
|
+
body = body.merge(optional_fields)
|
562
642
|
body_array = Array.new(1, body)
|
563
643
|
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
puts to_output_hash(e)
|
571
|
-
end
|
644
|
+
# Call the API
|
645
|
+
result = EmassClient::HardwareBaselineApi.new.add_hw_baseline_assets(options[:systemId], body_array)
|
646
|
+
puts to_output_hash(result).green
|
647
|
+
rescue EmassClient::ApiError => e
|
648
|
+
puts 'Exception when calling HardwareBaselineApi->add_hw_baseline_assets'.red
|
649
|
+
puts to_output_hash(e)
|
572
650
|
end
|
651
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
652
|
+
end
|
573
653
|
|
574
|
-
|
575
|
-
|
576
|
-
|
654
|
+
# Add Software Baseline assets for a system
|
655
|
+
#
|
656
|
+
# Endpoints:
|
657
|
+
# /api/systems/{systemId}/sw-baseline
|
658
|
+
class Software < SubCommandBase
|
659
|
+
def self.exit_on_failure?
|
660
|
+
true
|
661
|
+
end
|
662
|
+
|
663
|
+
desc 'add', 'Add one or many software assets into a system'
|
664
|
+
long_desc Help.text(:software_post_mapper)
|
577
665
|
|
578
666
|
# Required parameters/fields
|
579
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
580
|
-
option :
|
581
|
-
option :
|
582
|
-
option :
|
583
|
-
|
584
|
-
#
|
667
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
668
|
+
option :softwareVendor, aliases: '-V', type: :string, required: true, desc: 'Vendor of the software asset'
|
669
|
+
option :softwareName, aliases: '-N', type: :string, required: true, desc: 'Name of the software asset'
|
670
|
+
option :version, aliases: '-v', type: :string, required: true, desc: 'Version of the software asset'
|
671
|
+
|
672
|
+
# Conditional field
|
673
|
+
# If Approval Status is set to “Unapproved” or “In Progress”, Approval Date will be set to null.
|
674
|
+
option :approvalDate, type: :numeric, required: false, desc: 'Approval date of the software asset.'
|
675
|
+
|
676
|
+
# Optional fields
|
677
|
+
option :softwareType, type: :string, required: false, desc: 'Type of the software asset'
|
678
|
+
option :parentSystem, type: :string, required: false, desc: 'Parent system of the software asset'
|
679
|
+
option :subsystem, type: :string, required: false, desc: 'Subsystem of the software asset'
|
680
|
+
option :network, type: :string, required: false, desc: 'Network of the software asset'
|
681
|
+
option :hostingEnvironment, type: :string, required: false, desc: 'Hosting environment of the software asset'
|
682
|
+
option :softwareDependencies, type: :string, required: false, desc: 'Dependencies for the software asset'
|
683
|
+
option :cryptographicHash, type: :string, required: false, desc: 'Cryptographic hash for the software asset'
|
684
|
+
option :inServiceData, type: :string, required: false, desc: 'In service data for the software asset'
|
685
|
+
option :itBudgetUii, type: :string, required: false, desc: 'IT budget UII for the software asset'
|
686
|
+
option :fiscalYear, type: :string, required: false, desc: 'Fiscal year (FY) for the software asset'
|
687
|
+
option :popEndDate, type: :numeric, required: false, desc: 'Period of performance (POP) end date for the software asset'
|
688
|
+
option :licenseOrContract, type: :string, required: false, desc: 'License or contract for the software asset'
|
689
|
+
option :licenseTerm, type: :string, required: false, desc: 'License term for the software asset'
|
690
|
+
option :costPerLicense, type: :numeric, required: false, desc: 'Cost per license for the software asset'
|
691
|
+
option :totalLicenses, type: :numeric, required: false, desc: 'Number of total licenses for the software asset'
|
692
|
+
option :totalLicenseCost, type: :numeric, required: false, desc: 'Total cost of the licenses for the software asset'
|
693
|
+
option :licensesUsed, type: :numeric, required: false, desc: 'Number of licenses used for the software asset'
|
694
|
+
option :licensePoc, type: :string, required: false, desc: 'Point of contact (POC) for the software asset'
|
695
|
+
option :licenseRenewalDate, type: :numeric, required: false, desc: 'License renewal date for the software asset'
|
696
|
+
option :licenseExpirationDate, type: :numeric, required: false, desc: 'License expiration date for the software asset'
|
697
|
+
option :approvalStatus, type: :string, required: false, desc: 'Approval status of the software asset'
|
698
|
+
option :releaseDate, type: :numeric, required: false, desc: 'Release date of the software asset'
|
699
|
+
option :maintenanceDate, type: :numeric, required: false, desc: 'Maintenance date of the software asset'
|
700
|
+
option :retirementDate, type: :numeric, required: false, desc: 'Retirement date of the software asset'
|
701
|
+
option :endOfLifeSupportDate, type: :numeric, required: false, desc: 'End of life/support date of the software asset'
|
702
|
+
option :extendedEndOfLifeSupportDate, type: :numeric, required: false, desc: 'Extended End of Life/Support Date cannot occur prior to the End of Life/Support Date'
|
703
|
+
option :criticalAsset, type: :boolean, required: false, default: false, desc: 'Indicates whether the asset is a critical information system asset'
|
704
|
+
option :location, type: :string, required: false, desc: 'Location of the software asset'
|
705
|
+
option :purpose, type: :string, required: false, desc: 'Purpose of the software asset'
|
706
|
+
# VA only
|
707
|
+
option :unsupportedOperatingSystem, type: :boolean, required: false, default: false, desc: 'Unsupported operating system'
|
708
|
+
option :unapprovedSoftwareFromTrm, type: :boolean, required: false, default: false, desc: 'Unapproved software from TRM'
|
709
|
+
option :approvedWaiver, type: :boolean, required: false, default: false, desc: 'Approved waiver'
|
710
|
+
|
711
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
712
|
+
def add
|
713
|
+
# Required fields
|
714
|
+
require_field = EmassClient::SwBaselineRequiredFields.new
|
715
|
+
require_field.software_vendor = options[:softwareVendor]
|
716
|
+
require_field.software_name = options[:softwareName]
|
717
|
+
require_field.version = options[:version]
|
585
718
|
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
puts SCAN_POST_HELP_MESSAGE.yellow
|
590
|
-
exit
|
591
|
-
end
|
719
|
+
# Conditional fields
|
720
|
+
conditional_fields = EmassClient::SwBaselineConditionalFields.new
|
721
|
+
conditional_fields.approval_date = options[:approvalDate] if options[:approvalDate]
|
592
722
|
|
593
|
-
|
594
|
-
|
595
|
-
|
723
|
+
# Optional fields
|
724
|
+
optional_fields = EmassClient::SwBaselineOptionalFields.new
|
725
|
+
optional_fields.software_type = options[:softwareType] if options[:softwareType]
|
726
|
+
optional_fields.parent_system = options[:parentSystem] if options[:parentSystem]
|
727
|
+
optional_fields.subsystem = options[:subsystem] if options[:subsystem]
|
728
|
+
optional_fields.network = options[:network] if options[:network]
|
729
|
+
optional_fields.hosting_environment = options[:hostingEnvironment] if options[:hostingEnvironment]
|
730
|
+
optional_fields.software_dependencies = options[:softwareDependencies] if options[:softwareDependencies]
|
731
|
+
optional_fields.cryptographic_hash = options[:cryptographicHash] if options[:cryptographicHash]
|
732
|
+
optional_fields.in_service_data = options[:inServiceData] if options[:inServiceData]
|
733
|
+
optional_fields.it_budget_uii = options[:itBudgetUii] if options[:itBudgetUii]
|
734
|
+
optional_fields.fiscal_year = options[:fiscalYear] if options[:fiscalYear]
|
735
|
+
optional_fields.pop_end_date = options[:popEndDate] if options[:popEndDate]
|
736
|
+
optional_fields.license_or_contract = options[:licenseOrContract] if options[:licenseOrContract]
|
737
|
+
optional_fields.license_term = options[:licenseTerm] if options[:licenseTerm]
|
738
|
+
optional_fields.cost_per_license = options[:costPerLicense] if options[:costPerLicense]
|
739
|
+
optional_fields.total_licenses = options[:totalLicenses] if options[:totalLicenses]
|
740
|
+
optional_fields.total_license_cost = options[:totalLicenseCost] if options[:totalLicenseCost]
|
741
|
+
optional_fields.licenses_used = options[:licensesUsed] if options[:licensesUsed]
|
742
|
+
optional_fields.license_poc = options[:licensePoc] if options[:licensePoc]
|
743
|
+
optional_fields.license_renewal_date = options[:licenseRenewalDate] if options[:licenseRenewalDate]
|
744
|
+
optional_fields.license_expiration_date = options[:licenseExpirationDate] if options[:licenseExpirationDate]
|
745
|
+
optional_fields.approval_status = options[:approvalStatus] if options[:approvalStatus]
|
746
|
+
optional_fields.release_date = options[:releaseDate] if options[:releaseDate]
|
747
|
+
optional_fields.maintenance_date = options[:maintenanceDate] if options[:maintenanceDate]
|
748
|
+
optional_fields.retirement_date = options[:retirementDate] if options[:retirementDate]
|
749
|
+
optional_fields.end_of_life_support_date = options[:endOfLifeSupportDate] if options[:endOfLifeSupportDate]
|
750
|
+
optional_fields.extended_end_of_life_support_date = options[:extendedEndOfLifeSupportDate] if options[:extendedEndOfLifeSupportDate]
|
751
|
+
optional_fields.critical_asset = options[:criticalAsset] if options[:criticalAsset]
|
752
|
+
optional_fields.location = options[:location] if options[:location]
|
753
|
+
optional_fields.purpose = options[:purpose] if options[:purpose]
|
754
|
+
# VA only.
|
755
|
+
optional_fields.unsupported_operating_system = options[:unsupportedOperatingSystem] if options[:unsupportedOperatingSystem]
|
756
|
+
optional_fields.unapproved_software_from_trm = options[:unapprovedSoftwareFromTrm] if options[:unapprovedSoftwareFromTrm]
|
757
|
+
optional_fields.approved_waiver = options[:approvedWaiver] if options[:approvedWaiver]
|
758
|
+
|
759
|
+
# Build the body array
|
760
|
+
body = {}
|
761
|
+
body = body.merge(require_field)
|
762
|
+
body = body.merge(conditional_fields)
|
763
|
+
body = body.merge(optional_fields)
|
764
|
+
body_array = Array.new(1, body)
|
596
765
|
|
597
|
-
|
598
|
-
|
766
|
+
# Call the API
|
767
|
+
result = EmassClient::SoftwareBaselineApi.new.add_sw_baseline_assets(options[:systemId], body_array)
|
768
|
+
puts to_output_hash(result).green
|
769
|
+
rescue EmassClient::ApiError => e
|
770
|
+
puts 'Exception when calling SoftwareBaselineApi->add_sw_baseline_assets'.red
|
771
|
+
puts to_output_hash(e)
|
772
|
+
end
|
773
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
774
|
+
end
|
599
775
|
|
600
|
-
|
776
|
+
# Upload device scans (delivery method can be a file or a zip file)
|
777
|
+
#
|
778
|
+
# The body of a request for this endpoint accepts a single binary file.
|
779
|
+
# Specific file extensions are expected depending upon the scanType parameter.
|
780
|
+
# For example, .ckl or .cklb files are accepted when using scanType is set to
|
781
|
+
# disaStigViewerCklCklb.
|
782
|
+
#
|
783
|
+
# When set to acasAsrArf or policyAuditor, a .zip file is expected which
|
784
|
+
# should contain a single scan result (for example, a single pair of .asr and
|
785
|
+
# .arf files).
|
786
|
+
#
|
787
|
+
# Single files are expected for all other scan types as this endpoint requires
|
788
|
+
# files to be uploaded consecutively as opposed to in bulk.
|
789
|
+
#
|
790
|
+
# Current scan types that are supported:
|
791
|
+
# • ACAS: ASR/ARF
|
792
|
+
# • ACAS: NESSUS
|
793
|
+
# • DISA STIG Viewer: CKL/CKLB
|
794
|
+
# • DISA STIG Viewer: CMRS
|
795
|
+
# • Policy Auditor
|
796
|
+
# • SCAP Compliance Checker
|
797
|
+
#
|
798
|
+
# Endpoint:
|
799
|
+
# /api/systems/{systemId}/device-scan-results
|
800
|
+
class DeviceScans < SubCommandBase
|
801
|
+
def self.exit_on_failure?
|
802
|
+
true
|
803
|
+
end
|
601
804
|
|
602
|
-
|
603
|
-
body.application = application
|
604
|
-
body.application_findings = app_findings_array
|
805
|
+
desc 'upload', 'Uploads device scans into a system'
|
605
806
|
|
606
|
-
|
807
|
+
# Required parameters/fields
|
808
|
+
option :systemId, aliases: '-s', type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
809
|
+
option :filename, aliases: '-f', type: :string, required: true, desc: 'The device scan file'
|
810
|
+
option :scanType, aliases: '-t', type: :string, required: true, desc: 'The device scan type to upload',
|
811
|
+
enum: %w{acasAsrArf acasNessus disaStigViewerCklCklb disaStigViewerCmrs policyAuditor scapComplianceChecker}
|
812
|
+
|
813
|
+
# Optional parameters/fields - if not provided, default values are used
|
814
|
+
option :isBaseline, aliases: '-B', type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
|
815
|
+
|
816
|
+
def upload
|
817
|
+
# Check if business logic is satisfied
|
818
|
+
process_business_logic
|
819
|
+
|
820
|
+
# Options contain the default values (type, category, and isTemplate)
|
821
|
+
# They are sent to the API in the form_params option
|
822
|
+
opts = {}
|
823
|
+
opts[:isBaseline] = options[:isBaseline] if options[:isBaseline]
|
607
824
|
|
825
|
+
# Configure the upload file
|
608
826
|
begin
|
609
|
-
|
610
|
-
|
827
|
+
# If we have a single file, could be a zip file
|
828
|
+
if options[:filename]
|
829
|
+
tempfile = File.open(options[:filename], 'r')
|
830
|
+
else
|
831
|
+
puts 'One (1) file is expected!'.yellow
|
832
|
+
end
|
833
|
+
rescue Errno::ENOENT => e
|
834
|
+
warn "File open exception: #{e}".red
|
835
|
+
exit 1
|
836
|
+
end
|
837
|
+
|
838
|
+
# Call the API
|
839
|
+
begin
|
840
|
+
result = EmassClient::DeviceScanResultsApi
|
841
|
+
.new
|
842
|
+
.add_scan_results_by_system_id(options[:systemId], options[:scanType], tempfile, opts)
|
611
843
|
puts to_output_hash(result).green
|
612
844
|
rescue EmassClient::ApiError => e
|
613
|
-
puts 'Exception when calling
|
845
|
+
puts 'Exception when calling DeviceScanResultsApi->add_scan_results_by_system_id'.red
|
614
846
|
puts to_output_hash(e)
|
615
847
|
end
|
616
848
|
end
|
849
|
+
|
850
|
+
# rubocop:disable Style/MultipleComparison
|
851
|
+
no_commands do
|
852
|
+
def process_business_logic
|
853
|
+
# If scanType is set to disaStigViewerCklCklb a .ckl or .cklb file is expect
|
854
|
+
if options[:scanType] == 'disaStigViewerCklCklb' && !options[:filename].index('.ckl')
|
855
|
+
puts 'If the scan type is "disaStigViewerCklCklb" a .ckl or .cklb file is expected'.red
|
856
|
+
exit
|
857
|
+
# If scanType is set to acasAsrArf or policyAuditor a .zip file is expect
|
858
|
+
elsif options[:scanType] == 'acasAsrArf' || options[:scanType] == 'policyAuditor'
|
859
|
+
if !options[:filename].index('.zip')
|
860
|
+
puts 'If the scan type is "acasAsrArf or policyAuditor" a .zip file is expected'.red
|
861
|
+
exit
|
862
|
+
end
|
863
|
+
end
|
864
|
+
end
|
865
|
+
# rubocop:enable Style/MultipleComparison
|
866
|
+
end
|
617
867
|
end
|
618
868
|
|
619
869
|
# The Cloud Resources endpoint provides the ability to upload (add)
|
@@ -621,7 +871,7 @@ module Emasser
|
|
621
871
|
#
|
622
872
|
#
|
623
873
|
# Endpoint:
|
624
|
-
# /api/systems/{systemId}/cloud-resources-results
|
874
|
+
# /api/systems/{systemId}/cloud-resources-results
|
625
875
|
class CloudResource < SubCommandBase
|
626
876
|
def self.exit_on_failure?
|
627
877
|
true
|
@@ -636,7 +886,7 @@ module Emasser
|
|
636
886
|
option :resourceId, type: :string, required: true, desc: 'Unique identifier/resource namespace for policy compliance result'
|
637
887
|
option :resourceName, type: :string, required: true, desc: 'Friendly name of Cloud resource'
|
638
888
|
option :resourceType, type: :string, required: true, desc: 'Type of Cloud resource'
|
639
|
-
#
|
889
|
+
# compliance_results Array Objects (booleans cannot be required)
|
640
890
|
option :cspPolicyDefinitionId, type: :string, required: true, desc: 'Unique identifier/compliance namespace for CSP/Resource\'s policy definition/compliance check'
|
641
891
|
option :isCompliant, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false'
|
642
892
|
option :policyDefinitionTitle, type: :string, required: true, desc: 'Friendly policy/compliance check title. Recommend short title'
|
@@ -645,10 +895,10 @@ module Emasser
|
|
645
895
|
option :initiatedBy, type: :string, required: false, desc: 'Email of POC'
|
646
896
|
option :cspAccountId, type: :string, required: false, desc: 'System/owner\'s CSP account ID/number'
|
647
897
|
option :cspRegion, type: :string, required: false, desc: 'CSP region of system'
|
648
|
-
option :isBaseline, type: :boolean, required: false, default:
|
898
|
+
option :isBaseline, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false'
|
649
899
|
# Tags Object
|
650
900
|
option :test, type: :string, required: false, desc: 'The test tag'
|
651
|
-
#
|
901
|
+
# compliance_results Array Objects
|
652
902
|
option :assessmentProcedure, type: :string, required: false, desc: 'Comma separated correlation to Assessment Procedure (i.e. CCI number for DoD Control Set)'
|
653
903
|
option :complianceCheckTimestamp, type: :numeric, required: false, desc: 'The compliance timestamp Unix date format.'
|
654
904
|
option :complianceReason, type: :string, required: false, desc: 'Reason/comments for compliance result'
|
@@ -688,16 +938,16 @@ module Emasser
|
|
688
938
|
compliance_results[:policyDeploymentName] = options[:policyDeploymentName] if options[:policyDeploymentName]
|
689
939
|
compliance_results[:policyDeploymentVersion] = options[:policyDeploymentVersion] if options[:policyDeploymentVersion]
|
690
940
|
compliance_results[:severity] = options[:severity] if options[:severity]
|
691
|
-
|
692
941
|
compliance_results_array = Array.new(1, compliance_results)
|
693
942
|
|
943
|
+
# Build the body array
|
694
944
|
body[:tags] = tags
|
695
945
|
body[:complianceResults] = compliance_results_array
|
696
|
-
|
697
946
|
body_array = Array.new(1, body)
|
698
947
|
|
948
|
+
# Call the API
|
699
949
|
begin
|
700
|
-
result = EmassClient::
|
950
|
+
result = EmassClient::CloudResourceResultsApi
|
701
951
|
.new.add_cloud_resources_by_system_id(options[:systemId], body_array)
|
702
952
|
puts to_output_hash(result).green
|
703
953
|
rescue EmassClient::ApiError => e
|
@@ -713,7 +963,7 @@ module Emasser
|
|
713
963
|
#
|
714
964
|
#
|
715
965
|
# Endpoint:
|
716
|
-
# /api/systems/{systemId}/container-scan-results
|
966
|
+
# /api/systems/{systemId}/container-scan-results
|
717
967
|
class Container < SubCommandBase
|
718
968
|
def self.exit_on_failure?
|
719
969
|
true
|
@@ -727,9 +977,9 @@ module Emasser
|
|
727
977
|
option :containerId, type: :string, required: true, desc: 'Unique identifier of the container'
|
728
978
|
option :containerName, type: :string, required: true, desc: 'Friendly name of the container'
|
729
979
|
option :time, type: :numeric, required: true, desc: 'Datetime of scan/result. Unix date format'
|
730
|
-
# Benchmarks Array
|
980
|
+
# Benchmarks Array Object - Required
|
731
981
|
option :benchmark, type: :string, required: true, desc: 'Identifier of the benchmark/grouping of compliance results'
|
732
|
-
# Benchmarks.Results Array
|
982
|
+
# Benchmarks.Results Array Object - Required
|
733
983
|
option :lastSeen, type: :numeric, required: true, desc: 'Date last seen, Unix date format'
|
734
984
|
option :ruleId, type: :string, required: true, desc: 'Identifier for the compliance result, vulnerability, etc. the result is for'
|
735
985
|
option :status, type: :string, required: true, enum: ['Pass', 'Fail', 'Other', 'Not Reviewed', 'Not Checked', 'Not Applicable']
|
@@ -738,62 +988,175 @@ module Emasser
|
|
738
988
|
option :namespace, type: :string, required: false, desc: 'Namespace of container in container orchestration'
|
739
989
|
option :podIp, type: :string, required: false, desc: 'IP address of the pod'
|
740
990
|
option :podName, type: :string, required: false, desc: 'Name of pod (e.g. Kubernetes pod)'
|
741
|
-
|
991
|
+
|
992
|
+
# Tags Object - Optional
|
742
993
|
option :test, type: :string, required: false, desc: 'The test tag'
|
743
|
-
|
994
|
+
|
995
|
+
# Benchmarks Array Objects Optional
|
744
996
|
option :isBaseline, type: :boolean, required: false, default: true, desc: 'BOOLEAN - true or false'
|
745
|
-
|
997
|
+
option :version, type: :numeric, required: false, desc: 'The benchmark version'
|
998
|
+
option :release, type: :numeric, required: false, desc: 'The benchmark release'
|
999
|
+
|
1000
|
+
# Benchmarks.Results Array Object - Optional
|
746
1001
|
option :message, type: :string, required: false, desc: 'Benchmark result comments'
|
747
1002
|
|
748
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
1003
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
749
1004
|
def add
|
750
|
-
# Required
|
1005
|
+
# Required fields
|
751
1006
|
body = {}
|
752
1007
|
body[:containerId] = options[:containerId]
|
753
1008
|
body[:containerName] = options[:containerName]
|
754
1009
|
body[:time] = options[:time]
|
1010
|
+
# Optional fields
|
755
1011
|
body[:namespace] = options[:namespace] if options[:namespace]
|
756
1012
|
body[:podIp] = options[:podIp] if options[:podIp]
|
757
1013
|
body[:podName] = options[:podName] if options[:podName]
|
758
1014
|
|
759
|
-
# Optional
|
1015
|
+
# Tags - Optional field
|
760
1016
|
tags = {}
|
761
1017
|
tags[:test] = options[:test] if options[:test]
|
762
1018
|
|
763
|
-
#
|
1019
|
+
# Benchmarks - Required field
|
764
1020
|
benchmarks = {}
|
765
1021
|
benchmarks[:benchmark] = options[:benchmark]
|
766
|
-
# Optional fields
|
1022
|
+
# Benchmarks - Optional fields
|
767
1023
|
benchmarks[:isBaseline] = options[:isBaseline] if options[:isBaseline]
|
1024
|
+
benchmarks[:version] = options[:version] if options[:version]
|
1025
|
+
benchmarks[:release] = options[:release] if options[:release]
|
768
1026
|
|
769
|
-
#
|
1027
|
+
# Benchmarks.Results - Required fields
|
770
1028
|
benchmarks_results = {}
|
771
1029
|
benchmarks_results[:lastSeen] = options[:lastSeen]
|
772
1030
|
benchmarks_results[:ruleId] = options[:ruleId]
|
773
1031
|
benchmarks_results[:status] = options[:status]
|
1032
|
+
# Benchmarks.Results - Optional field
|
774
1033
|
benchmarks_results[:message] = options[:message] if options[:message]
|
775
1034
|
|
776
1035
|
# Add Benchmark results to an array and add array to benchmarks object
|
777
1036
|
benchmarks_results_array = Array.new(1, benchmarks_results)
|
778
|
-
benchmarks[:results] = benchmarks_results_array
|
1037
|
+
benchmarks[:results] = benchmarks_results_array
|
1038
|
+
|
779
1039
|
# Add benchmarks object to an array
|
780
1040
|
benchmarks_array = Array.new(1, benchmarks)
|
781
1041
|
# Add tags and benchmark ojects to body object
|
782
|
-
body[:tags] = tags
|
1042
|
+
body[:tags] = tags if tags.any?
|
783
1043
|
body[:benchmarks] = benchmarks_array
|
784
1044
|
|
1045
|
+
# Build the body array
|
785
1046
|
body_array = Array.new(1, body)
|
786
1047
|
|
1048
|
+
# Call the API
|
787
1049
|
begin
|
788
|
-
result = EmassClient::
|
1050
|
+
result = EmassClient::ContainerScanResultsApi
|
789
1051
|
.new.add_container_sans_by_system_id(options[:systemId], body_array)
|
790
1052
|
puts to_output_hash(result).green
|
791
1053
|
rescue EmassClient::ApiError => e
|
792
|
-
puts 'Exception when calling
|
1054
|
+
puts 'Exception when calling ContainerScanResultsApi->add_container_sans_by_system_id'.red
|
1055
|
+
puts to_output_hash(e)
|
1056
|
+
end
|
1057
|
+
end
|
1058
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
# The Static Code Scans endpoint provides the ability to upload application
|
1062
|
+
# scan findings into a system's assets module.
|
1063
|
+
#
|
1064
|
+
# Application findings can also be cleared from the system.
|
1065
|
+
#
|
1066
|
+
# Endpoint:
|
1067
|
+
# /api/systems/{systemId}/static-code-scans - Upload static code scans
|
1068
|
+
class ScanFindings < SubCommandBase
|
1069
|
+
def self.exit_on_failure?
|
1070
|
+
true
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
desc 'add', 'Upload static code scans'
|
1074
|
+
long_desc Help.text(:staticcode_post_mapper)
|
1075
|
+
|
1076
|
+
# Required parameters/fields
|
1077
|
+
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
1078
|
+
option :applicationName, type: :string, required: true, desc: 'Name of the software application that was assessed'
|
1079
|
+
option :version, type: :string, required: true, desc: 'The version of the application'
|
1080
|
+
option :codeCheckName, type: :string, required: true, desc: 'Name of the software vulnerability or weakness'
|
1081
|
+
option :scanDate, type: :numeric, required: true, desc: 'The findings scan date - Unix time format'
|
1082
|
+
option :cweId, type: :string, required: true, desc: 'The Common Weakness Enumerator (CWE) identifier'
|
1083
|
+
option :count, type: :numeric, required: true, desc: 'Number of instances observed for a specified finding'
|
1084
|
+
# Optional parameter/fields
|
1085
|
+
option :rawSeverity, type: :string, required: false, enum: %w[Low Medium Moderate High Critical]
|
1086
|
+
|
1087
|
+
def add
|
1088
|
+
application = EmassClient::StaticCodeRequestPostBodyApplication.new
|
1089
|
+
application.application_name = options[:applicationName]
|
1090
|
+
application.version = options[:version]
|
1091
|
+
|
1092
|
+
application_findings = EmassClient::StaticCodeApplicationPost.new
|
1093
|
+
application_findings.code_check_name = options[:codeCheckName]
|
1094
|
+
application_findings.scan_date = options[:scanDate]
|
1095
|
+
application_findings.cwe_id = options[:cweId]
|
1096
|
+
application_findings.count = options[:count]
|
1097
|
+
application_findings.raw_severity = options[:rawSeverity] if options[:rawSeverity]
|
1098
|
+
|
1099
|
+
app_findings_array = Array.new(1, application_findings)
|
1100
|
+
|
1101
|
+
body = EmassClient::StaticCodeRequestPostBody.new
|
1102
|
+
body.application = application
|
1103
|
+
body.application_findings = app_findings_array
|
1104
|
+
|
1105
|
+
body_array = Array.new(1, body)
|
1106
|
+
|
1107
|
+
begin
|
1108
|
+
result = EmassClient::StaticCodeScansApi
|
1109
|
+
.new.add_static_code_scans_by_system_id(options[:systemId], body_array)
|
1110
|
+
puts to_output_hash(result).green
|
1111
|
+
rescue EmassClient::ApiError => e
|
1112
|
+
puts 'Exception when calling StaticCodeScansApi->add_static_code_scans_by_system_id'.red
|
1113
|
+
puts to_output_hash(e)
|
1114
|
+
end
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
# CLEAR ------------------------------------------------------------------------------------
|
1118
|
+
desc 'clear', 'Clear an application findings'
|
1119
|
+
long_desc Help.text(:staticcode_clear_mapper)
|
1120
|
+
|
1121
|
+
# Required parameters/fields
|
1122
|
+
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
1123
|
+
option :applicationName, type: :string, required: true, desc: 'Name of the software application that was assessed'
|
1124
|
+
option :version, type: :string, required: true, desc: 'The version of the application'
|
1125
|
+
option :clearFindings, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false'
|
1126
|
+
# NOTE: clearFindings is a required parameter to clear an application's findings, however Thor does not allow
|
1127
|
+
# a boolean type to be required because it automatically creates a --no-clearFindings option for clearFindings=false
|
1128
|
+
|
1129
|
+
def clear
|
1130
|
+
unless options[:clearFindings]
|
1131
|
+
puts 'To clear an application findings, the field clearFindings (--clearFindings) is required'.red
|
1132
|
+
puts SCAN_POST_HELP_MESSAGE.yellow
|
1133
|
+
exit
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
application = EmassClient::StaticCodeRequestPostBodyApplication.new
|
1137
|
+
application.application_name = options[:applicationName]
|
1138
|
+
application.version = options[:version]
|
1139
|
+
|
1140
|
+
application_findings = EmassClient::StaticCodeApplicationPost.new
|
1141
|
+
application_findings.clear_findings = options[:clearFindings]
|
1142
|
+
|
1143
|
+
app_findings_array = Array.new(1, application_findings)
|
1144
|
+
|
1145
|
+
body = EmassClient::StaticCodeRequestPostBody.new
|
1146
|
+
body.application = application
|
1147
|
+
body.application_findings = app_findings_array
|
1148
|
+
|
1149
|
+
body_array = Array.new(1, body)
|
1150
|
+
|
1151
|
+
begin
|
1152
|
+
result = EmassClient::StaticCodeScansApi
|
1153
|
+
.new.add_static_code_scans_by_system_id(options[:systemId], body_array)
|
1154
|
+
puts to_output_hash(result).green
|
1155
|
+
rescue EmassClient::ApiError => e
|
1156
|
+
puts 'Exception when calling StaticCodeScansApi->add_static_code_scans_by_system_id'.red
|
793
1157
|
puts to_output_hash(e)
|
794
1158
|
end
|
795
1159
|
end
|
796
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
797
1160
|
end
|
798
1161
|
|
799
1162
|
class Post < SubCommandBase
|
@@ -818,13 +1181,22 @@ module Emasser
|
|
818
1181
|
desc 'pac', 'Add Package Approval Chain (PAC) security content'
|
819
1182
|
subcommand 'pac', PAC
|
820
1183
|
|
821
|
-
desc '
|
822
|
-
subcommand '
|
1184
|
+
desc 'hardware', 'Add one or many hardware assets to a system'
|
1185
|
+
subcommand 'hardware', Hardware
|
1186
|
+
|
1187
|
+
desc 'software', 'Add one or many software assets to a system'
|
1188
|
+
subcommand 'software', Software
|
1189
|
+
|
1190
|
+
desc 'device_scans', 'Upload device scan results for a system'
|
1191
|
+
subcommand 'device_scans', DeviceScans
|
823
1192
|
|
824
1193
|
desc 'cloud_resource', 'Upload cloud resource and their scan results'
|
825
1194
|
subcommand 'cloud_resource', CloudResource
|
826
1195
|
|
827
1196
|
desc 'container', 'Upload container and their scan results'
|
828
1197
|
subcommand 'container', Container
|
1198
|
+
|
1199
|
+
desc 'scan_findings', 'Upload static code scans'
|
1200
|
+
subcommand 'scan_findings', ScanFindings
|
829
1201
|
end
|
830
1202
|
end
|