emasser 3.4.1 → 3.10.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/.dockerignore +8 -8
- data/.env-example +12 -12
- data/.github/release-drafter.yml +15 -15
- data/.github/workflows/codeql-analysis.yml +70 -70
- data/.github/workflows/draft-release.yml +15 -15
- data/.github/workflows/gh-pages.yml +32 -32
- data/.github/workflows/push-to-docker-mail.yml +28 -28
- data/.github/workflows/push-to-docker.yml +35 -35
- data/.github/workflows/release.yml +42 -42
- data/.github/workflows/rubocop.yml +23 -23
- data/.github/workflows/test-cli.yml +39 -72
- data/.gitignore +19 -19
- data/.mergify.yml +25 -25
- data/.rubocop.yml +83 -80
- data/.rubocop_todo.yml +27 -27
- data/CHANGELOG.md +16 -16
- data/Dockerfile +44 -44
- data/Gemfile +8 -8
- data/Gemfile.lock +108 -104
- data/LICENSE.md +15 -15
- data/README.md +178 -178
- data/Rakefile +18 -18
- data/_config.yml +1 -1
- data/docs/features.md +1501 -1436
- data/docs/redoc/index.html +1230 -1230
- data/emasser.gemspec +44 -44
- data/exe/emasser +5 -5
- data/lib/emasser/cli.rb +37 -37
- data/lib/emasser/configuration.rb +49 -49
- data/lib/emasser/constants.rb +26 -26
- data/lib/emasser/delete.rb +148 -148
- data/lib/emasser/errors.rb +14 -14
- data/lib/emasser/get.rb +1194 -949
- data/lib/emasser/help/approvalCac_post_mapper.md +20 -20
- data/lib/emasser/help/approvalPac_post_mapper.md +20 -20
- data/lib/emasser/help/artifacts_del_mapper.md +9 -9
- data/lib/emasser/help/artifacts_post_mapper.md +59 -59
- data/lib/emasser/help/artifacts_put_mapper.md +34 -34
- data/lib/emasser/help/cloudresource_post_mapper.md +62 -62
- data/lib/emasser/help/cmmc_get_mapper.md +4 -4
- data/lib/emasser/help/container_post_mapper.md +44 -44
- data/lib/emasser/help/controls_put_mapper.md +74 -74
- data/lib/emasser/help/milestone_del_mapper.md +11 -11
- data/lib/emasser/help/milestone_post_mapper.md +14 -14
- data/lib/emasser/help/milestone_put_mapper.md +23 -23
- data/lib/emasser/help/poam_del_mapper.md +5 -5
- data/lib/emasser/help/poam_post_mapper.md +93 -93
- data/lib/emasser/help/poam_put_mapper.md +107 -107
- data/lib/emasser/help/staticcode_clear_mapper.md +16 -16
- data/lib/emasser/help/staticcode_post_mapper.md +21 -21
- data/lib/emasser/help/testresults_post_mapper.md +21 -21
- data/lib/emasser/help.rb +11 -11
- data/lib/emasser/input_converters.rb +21 -21
- data/lib/emasser/options_parser.rb +20 -20
- data/lib/emasser/output_converters.rb +115 -111
- data/lib/emasser/post.rb +830 -830
- data/lib/emasser/put.rb +588 -588
- data/lib/emasser/version.rb +5 -5
- data/lib/emasser.rb +19 -19
- metadata +16 -10
data/lib/emasser/put.rb
CHANGED
@@ -1,588 +1,588 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Hack class that properly formats the CLI help
|
4
|
-
class SubCommandBase < Thor
|
5
|
-
include OutputConverters
|
6
|
-
|
7
|
-
# We do not control the method declaration for the banner
|
8
|
-
|
9
|
-
# rubocop:disable Style/OptionalBooleanParameter
|
10
|
-
def self.banner(command, _namespace = nil, subcommand = false)
|
11
|
-
# Use the $thor_runner (declared by the Thor CLI framework)
|
12
|
-
# to properly format the help text of sub-sub-commands.
|
13
|
-
|
14
|
-
# rubocop:disable Style/GlobalVars
|
15
|
-
if ancestors[0].to_s.include? '::Put'
|
16
|
-
"#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
|
17
|
-
else
|
18
|
-
"#{basename} put #{command.formatted_usage(self, $thor_runner, subcommand)}"
|
19
|
-
end
|
20
|
-
# rubocop:enable Style/GlobalVars
|
21
|
-
end
|
22
|
-
# rubocop:enable Style/OptionalBooleanParameter
|
23
|
-
end
|
24
|
-
|
25
|
-
# Override thor's long_desc identation behavior
|
26
|
-
class Thor
|
27
|
-
module Shell
|
28
|
-
class Basic
|
29
|
-
def print_wrapped(message, _options = {})
|
30
|
-
message = "\n#{message}\n" unless message[0] == "\n"
|
31
|
-
stdout.puts message
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
module Emasser
|
38
|
-
CONTROLS_PUT_HELP_MESSAGE = "\nInvoke \"bundle exec exe/emasser put controls help update\" for additional help"
|
39
|
-
POAMS_PUT_HELP_MESSAGE = "\nInvoke \"bundle exec exe/emasser put poams help add\" for additional help"
|
40
|
-
# Update Security Control information of a system for both the Implementation Plan and Risk Assessment.
|
41
|
-
#
|
42
|
-
# Endpoint:
|
43
|
-
# /api/systems/{systemId}/controls - Update control information in a system for one or many controls
|
44
|
-
# rubocop:disable Style/WordArray
|
45
|
-
class Controls < SubCommandBase
|
46
|
-
def self.exit_on_failure?
|
47
|
-
true
|
48
|
-
end
|
49
|
-
|
50
|
-
desc 'update', 'Get control information in a system for one or many controls (acronym)'
|
51
|
-
long_desc Help.text(:controls_put_mapper)
|
52
|
-
|
53
|
-
# Required parameters/fields
|
54
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
55
|
-
option :acronym, type: :string, required: true, desc: 'The system acronym(s) e.g "AC-1, AC-2"'
|
56
|
-
option :responsibleEntities, type: :string, required: true,
|
57
|
-
desc: 'Description of the responsible entities for the Security Control'
|
58
|
-
option :controlDesignation, type: :string, required: true,
|
59
|
-
enum: ['Common', 'System-Specific', 'Hybrid'],
|
60
|
-
desc: 'The Security Control Designation'
|
61
|
-
option :estimatedCompletionDate, type: :numeric, required: true, desc: 'Estimated completion date, Unix time format'
|
62
|
-
option :implementationNarrative, type: :string, required: true, desc: 'Security control comments'
|
63
|
-
|
64
|
-
# Conditional parameters/fields
|
65
|
-
option :commonControlProvider,
|
66
|
-
type: :string,
|
67
|
-
required: false,
|
68
|
-
enum: ['DoD', 'Component', 'Enclave'],
|
69
|
-
desc: 'Indicate the type of Common Control Provider for an "Inherited" Security Control'
|
70
|
-
option :naJustification,
|
71
|
-
type: :string, required: false,
|
72
|
-
desc: 'Provide justification for Security Controls deemed Not Applicable to the system'
|
73
|
-
option :slcmCriticality,
|
74
|
-
type: :string, required: false,
|
75
|
-
desc: 'Criticality of Security Control regarding SLCM'
|
76
|
-
option :slcmFrequency,
|
77
|
-
type: :string, required: false,
|
78
|
-
enum: ['Constantly', 'Daily', 'Weekly', 'Monthly', 'Quarterly', 'Semi-Annually',
|
79
|
-
'Annually', 'Every Two Years', 'Every Three Years', 'Undetermined'],
|
80
|
-
desc: 'The System-Level Continuous Monitoring frequency'
|
81
|
-
option :slcmMethod,
|
82
|
-
type: :string, required: false,
|
83
|
-
enum: ['Automated', 'Semi-Automated', 'Manual', 'Undetermined'],
|
84
|
-
desc: 'The System-Level Continuous Monitoring method'
|
85
|
-
option :slcmReporting,
|
86
|
-
type: :string, required: false,
|
87
|
-
desc: 'The System-Level Continuous Monitoring reporting'
|
88
|
-
option :slcmTracking,
|
89
|
-
type: :string, required: false,
|
90
|
-
desc: 'The System-Level Continuous Monitoring tracking'
|
91
|
-
option :slcmComments,
|
92
|
-
type: :string, required: false,
|
93
|
-
desc: 'Additional comments for Security Control regarding SLCM'
|
94
|
-
|
95
|
-
# Optional parameters/fields
|
96
|
-
option :implementationStatus,
|
97
|
-
type: :string, required: false,
|
98
|
-
enum: ['Planned', 'Implemented', 'Inherited', 'Not Applicable', 'Manually Inherited'],
|
99
|
-
desc: 'Implementation status of the security control for the information system'
|
100
|
-
option :severity,
|
101
|
-
type: :string, required: false,
|
102
|
-
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
103
|
-
desc: 'The security control severity, required for approved items'
|
104
|
-
option :vulnerabiltySummary, type: :string, required: false, desc: 'The security control vulnerability summary'
|
105
|
-
option :recommendations, type: :string, required: false, desc: 'The security control vulnerability recommendation'
|
106
|
-
option :relevanceOfThreat,
|
107
|
-
type: :string, required: false,
|
108
|
-
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
109
|
-
desc: 'The security control vulnerability of threat'
|
110
|
-
option :likelihood,
|
111
|
-
type: :string, required: false,
|
112
|
-
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
113
|
-
desc: 'The security control likelihood of vulnerability to threats'
|
114
|
-
option :impact,
|
115
|
-
type: :string, required: false,
|
116
|
-
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
117
|
-
desc: 'The security control vulnerability impact'
|
118
|
-
option :impactDescription, type: :string, required: false, desc: 'Description of the security control impact'
|
119
|
-
option :residualRiskLevel,
|
120
|
-
type: :string, required: false,
|
121
|
-
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
122
|
-
desc: 'The security control risk level'
|
123
|
-
option :testMethod,
|
124
|
-
type: :string, required: false,
|
125
|
-
enum: ['Test', 'Interview', 'Examine', 'Test, Interview', 'Test, Examine',
|
126
|
-
'Interview, Examine', 'Test, Interview, Examine'],
|
127
|
-
desc: 'Assessment method/combination that determines if the security requirements are implemented correctly'
|
128
|
-
|
129
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
130
|
-
def update
|
131
|
-
# Required fields
|
132
|
-
body = EmassClient::ControlsGet.new
|
133
|
-
body.acronym = options[:acronym]
|
134
|
-
body.responsible_entities = options[:responsibleEntities]
|
135
|
-
body.control_designation = options[:controlDesignation]
|
136
|
-
body.estimated_completion_date = options[:estimatedCompletionDate]
|
137
|
-
body.implementation_narrative = options[:implementationNarrative]
|
138
|
-
|
139
|
-
process_business_logic(body)
|
140
|
-
|
141
|
-
# Add optional fields
|
142
|
-
body.severity = options[:severity] if options[:severity]
|
143
|
-
body.vulnerabilty_summary = options[:vulnerabiltySummary] if options[:vulnerabiltySummary]
|
144
|
-
body.recommendations = options[:recommendations] if options[:recommendations]
|
145
|
-
body.relevance_of_threat = options[:relevanceOfThreat] if options[:relevanceOfThreat]
|
146
|
-
body.likelihood = options[:likelihood] if options[:likelihood]
|
147
|
-
body.impact = options[:impact] if options[:impact]
|
148
|
-
body.impact_description = options[:impactDescription] if options[:impactDescription]
|
149
|
-
body.residual_risk_level = options[:residualRiskLevel] if options[:residualRiskLevel]
|
150
|
-
body.test_method = options[:testMethod] if options[:testMethod]
|
151
|
-
|
152
|
-
body_array = Array.new(1, body)
|
153
|
-
|
154
|
-
begin
|
155
|
-
result = EmassClient::ControlsApi.new.update_control_by_system_id(options[:systemId], body_array)
|
156
|
-
puts to_output_hash(result).green
|
157
|
-
rescue EmassClient::ApiError => e
|
158
|
-
puts 'Exception when calling ControlsApi->update_control_by_system_id'.red
|
159
|
-
puts to_output_hash(e)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
163
|
-
|
164
|
-
# rubocop:disable Style/CaseLikeIf, Style/StringLiterals, Metrics/BlockLength, Metrics/CyclomaticComplexity
|
165
|
-
no_commands do
|
166
|
-
# rubocop:disable Metrics/PerceivedComplexity, Style/GuardClause
|
167
|
-
def process_business_logic(body)
|
168
|
-
# Conditional fields based on implementationStatus content
|
169
|
-
# unless executes code if conditional is false
|
170
|
-
unless options[:implementationStatus].nil?
|
171
|
-
body.implementation_status = options[:implementationStatus]
|
172
|
-
|
173
|
-
if options[:implementationStatus] == "Planned" || options[:implementationStatus] == "Implemented"
|
174
|
-
if options[:responsibleEntities].nil? || options[:slcmCriticality].nil? ||
|
175
|
-
options[:slcmFrequency].nil? || options[:slcmMethod].nil? ||
|
176
|
-
options[:slcmReporting].nil? || options[:slcmTracking].nil? || options[:slcmComments].nil?
|
177
|
-
puts 'Missing one of these parameters/fields:'.red
|
178
|
-
puts ' responsibleEntities, slcmCriticality, slcmFrequency,'.red
|
179
|
-
puts ' slcmMethod,slcmReporting, slcmTracking, slcmComments'.red
|
180
|
-
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
181
|
-
exit
|
182
|
-
else
|
183
|
-
body.responsible_entities = options[:responsibleEntities]
|
184
|
-
body.slcm_criticality = options[:slcmCriticality]
|
185
|
-
body.slcm_frequency = options[:slcmFrequency]
|
186
|
-
body.slcm_method = options[:slcmMethod]
|
187
|
-
body.slcm_reporting = options[:slcmReporting]
|
188
|
-
body.slcm_tracking = options[:slcmTracking]
|
189
|
-
body.slcm_comments = options[:slcmComments]
|
190
|
-
end
|
191
|
-
elsif options[:implementationStatus] == 'Not Applicable'
|
192
|
-
if options[:naJustification].nil? || options[:responsibleEntities].nil?
|
193
|
-
puts 'Missing one of these parameters/fields:'.red
|
194
|
-
puts ' naJustification, responsibleEntities'.red
|
195
|
-
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
196
|
-
exit
|
197
|
-
else
|
198
|
-
body.slcm_reporting = options[:naJustification]
|
199
|
-
body.responsible_entities = options[:responsibleEntities]
|
200
|
-
end
|
201
|
-
elsif options[:implementationStatus] == 'Manually Inherited'
|
202
|
-
if options[:commonControlProvider].nil? || options[:responsibleEntities].nil? ||
|
203
|
-
options[:slcmCriticality].nil? || options[:slcmFrequency].nil? || options[:slcmMethod].nil? ||
|
204
|
-
options[:slcmReporting].nil? || options[:slcmTracking].nil? || options[:slcmComments].nil?
|
205
|
-
puts 'Missing one of these parameters/fields:'.red
|
206
|
-
puts ' commonControlProvider, responsibleEntities, slcmCriticality,'.red
|
207
|
-
puts ' slcmFrequency, slcmMethod, slcmReporting, slcmTracking, slcmComments'.red
|
208
|
-
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
209
|
-
exit
|
210
|
-
else
|
211
|
-
body.common_control_provider = options[:commonControlProvider]
|
212
|
-
body.responsible_entities = options[:responsibleEntities]
|
213
|
-
body.slcm_criticality = options[:slcmCriticality]
|
214
|
-
body.slcm_frequency = options[:slcmFrequency]
|
215
|
-
body.slcm_method = options[:slcmMethod]
|
216
|
-
body.slcm_reporting = options[:slcmReporting]
|
217
|
-
body.slcm_tracking = options[:slcmTracking]
|
218
|
-
body.slcm_comments = options[:slcmComments]
|
219
|
-
end
|
220
|
-
elsif options[:implementationStatus] == 'Inherited'
|
221
|
-
if options[:commonControlProvider].nil?
|
222
|
-
puts 'When implementationStatus value is "Inherited" only the following fields are updated:'.red
|
223
|
-
puts ' controlDesignation and commonControlProvider'.red
|
224
|
-
puts 'Missing the commonControlProvider field'.red
|
225
|
-
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
226
|
-
exit
|
227
|
-
else
|
228
|
-
body.common_control_provider = options[:commonControlProvider]
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
# rubocop:enable Metrics/PerceivedComplexity, Style/GuardClause
|
234
|
-
end
|
235
|
-
# rubocop:enable Style/CaseLikeIf, Style/StringLiterals, Metrics/BlockLength, Metrics/CyclomaticComplexity
|
236
|
-
end
|
237
|
-
# rubocop:enable Style/WordArray
|
238
|
-
|
239
|
-
# Update Plan of Action (POA&M) items to a system.
|
240
|
-
#
|
241
|
-
# Endpoint:
|
242
|
-
# /api/systems/{systemId}/poams - Update one or many poa&m items in a system
|
243
|
-
class Poams < SubCommandBase
|
244
|
-
def self.exit_on_failure?
|
245
|
-
true
|
246
|
-
end
|
247
|
-
|
248
|
-
# Update a POAM -----------------------------------------------------------
|
249
|
-
#
|
250
|
-
# The following fields are required based on the contents of the status field
|
251
|
-
# status Required Fields
|
252
|
-
# -------------------------------------------------------------------------
|
253
|
-
# Risk Accepted comments, resources
|
254
|
-
# Ongoing scheduledCompletionDate, resources, milestones (at least 1)
|
255
|
-
# Completed scheduledCompletionDate, comments, resources,
|
256
|
-
# completionDate, milestones (at least 1)
|
257
|
-
# Not Applicable POAM can not be created
|
258
|
-
#--------------------------------------------------------------------------
|
259
|
-
#
|
260
|
-
# If a POC email is supplied, the application will attempt to locate a user
|
261
|
-
# already registered within the application and pre-populate any information
|
262
|
-
# not explicitly supplied in the request. If no such user is found, these
|
263
|
-
# fields are required within the request.
|
264
|
-
# pocOrganization, pocFirstName, pocLastName, pocEmail, pocPhoneNumber
|
265
|
-
|
266
|
-
desc 'update', 'Update one or many POA&M items in a system'
|
267
|
-
long_desc Help.text(:poam_put_mapper)
|
268
|
-
|
269
|
-
# Required parameters/fields
|
270
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
271
|
-
option :poamId, type: :numeric, required: true, desc: 'A numeric value representing the poam identification'
|
272
|
-
# option :displayPoamId,
|
273
|
-
# type: :numeric, required: true,
|
274
|
-
# desc: 'Globally unique identifier for individual POA&M Items, seen on the front-end as "ID"'
|
275
|
-
option :status, type: :string, required: true, enum: ['Ongoing', 'Risk Accepted', 'Completed', 'Not Applicable']
|
276
|
-
option :vulnerabilityDescription, type: :string, required: true, desc: 'POA&M vulnerability description'
|
277
|
-
option :sourceIdentVuln,
|
278
|
-
type: :string, required: true, desc: 'Source that identifies the vulnerability'
|
279
|
-
option :pocOrganization, type: :string, required: true, desc: 'Organization/Office represented'
|
280
|
-
option :resources, type: :string, required: true, desc: 'List of resources used'
|
281
|
-
|
282
|
-
# Conditional parameters/fields
|
283
|
-
option :milestone,
|
284
|
-
type: :hash, required: false, desc: 'key:values are: milestoneId, description and scheduledCompletionDate'
|
285
|
-
option :pocFirstName, type: :string, required: false, desc: 'First name of POC'
|
286
|
-
option :pocLastName, type: :string, required: false, desc: 'Last name of POC.'
|
287
|
-
option :pocEmail, type: :string, required: false, desc: 'Email address of POC'
|
288
|
-
option :pocPhoneNumber, type: :string, required: false, desc: 'Phone number of POC (area code) ***-**** format'
|
289
|
-
option :severity, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
290
|
-
option :scheduledCompletionDate,
|
291
|
-
type: :numeric, required: false, desc: 'The scheduled completion date - Unix time format'
|
292
|
-
option :completionDate,
|
293
|
-
type: :numeric, required: false, desc: 'The schedule completion date - Unix time format'
|
294
|
-
option :comments, type: :string, required: false, desc: 'Comments for completed and risk accepted POA&M items'
|
295
|
-
option :isActive, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
|
296
|
-
|
297
|
-
# Optional parameters/fields
|
298
|
-
option :externalUid, type: :string, required: false, desc: 'External ID associated with the POA&M'
|
299
|
-
option :controlAcronym, type: :string, required: false, desc: 'The system acronym(s) e.g "AC-1, AC-2"'
|
300
|
-
option :cci, type: :string, required: false, desc: 'The system CCIS string numerical value'
|
301
|
-
option :securityChecks, type: :string, required: false, desc: 'Security Checks that are associated with the POA&M'
|
302
|
-
option :rawSeverity, type: :string, required: false, enum: %w[I II III]
|
303
|
-
option :relevanceOfThreat,
|
304
|
-
type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
305
|
-
option :likelihood, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
306
|
-
option :impact, type: :string, required: false, desc: 'Description of Security Control’s impact'
|
307
|
-
option :impactDescription, type: :string, required: false, desc: 'Description of the security control impact'
|
308
|
-
option :residualRiskLevel,
|
309
|
-
type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
310
|
-
option :recommendations, type: :string, required: false, desc: 'Recomendations'
|
311
|
-
option :mitigation, type: :string, required: false, desc: 'Mitigation explanation'
|
312
|
-
|
313
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
314
|
-
def update
|
315
|
-
# Required fields
|
316
|
-
body = EmassClient::PoamGet.new
|
317
|
-
body.poam_id = options[:poamId]
|
318
|
-
body.status = options[:status]
|
319
|
-
body.vulnerability_description = options[:vulnerabilityDescription]
|
320
|
-
body.source_ident_vuln = options[:sourceIdentVuln]
|
321
|
-
body.poc_organization = options[:pocOrganization]
|
322
|
-
body.resources = options[:resources]
|
323
|
-
|
324
|
-
process_business_logic(body)
|
325
|
-
|
326
|
-
# Add conditional fields
|
327
|
-
body.poc_first_name = options[:pocFirstName] if options[:pocFirstName]
|
328
|
-
body.poc_last_name = options[:pocLastName] if options[:pocLastName]
|
329
|
-
body.poc_email = options[:pocEmail] if options[:pocEmail]
|
330
|
-
body.poc_phone_number = options[:pocPhoneNumber] if options[:pocPhoneNumber]
|
331
|
-
body.severity = options[:severity] if options[:severity]
|
332
|
-
|
333
|
-
# Add optional fields
|
334
|
-
body.external_uid = options[:externalUid] if options[:externalUid]
|
335
|
-
body.control_acronym = options[:controlAcronym] if options[:controlAcronym]
|
336
|
-
body.cci = options[:cci] if options[:cci]
|
337
|
-
body.security_checks = options[:securityChecks] if options[:securityChecks]
|
338
|
-
body.raw_severity = options[:rawSeverity] if options[:rawSeverity]
|
339
|
-
body.relevance_of_threat = options[:relevanceOfThreat] if options[:relevanceOfThreat]
|
340
|
-
body.likelihood = options[:likelihood] if options[:likelihood]
|
341
|
-
body.impact = options[:impact] if options[:impact]
|
342
|
-
body.impact_description = options[:impactDescription] if options[:impactDescription]
|
343
|
-
body.residual_risk_level = options[:residualRiskLevel] if options[:residualRiskLevel]
|
344
|
-
body.recommendations = options[:recommendations] if options[:recommendations]
|
345
|
-
body.mitigation = options[:mitigation] if options[:mitigation]
|
346
|
-
|
347
|
-
body_array = Array.new(1, body)
|
348
|
-
|
349
|
-
begin
|
350
|
-
result = EmassClient::POAMApi.new.update_poam_by_system_id(options[:systemId], body_array)
|
351
|
-
puts to_output_hash(result).green
|
352
|
-
rescue EmassClient::ApiError => e
|
353
|
-
puts 'Exception when calling POAMApi->update_poam_by_system_id'.red
|
354
|
-
puts to_output_hash(e)
|
355
|
-
end
|
356
|
-
end
|
357
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
358
|
-
|
359
|
-
# rubocop:disable Metrics/AbcSize, Metrics/BlockLength, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
360
|
-
no_commands do
|
361
|
-
def process_business_logic(body)
|
362
|
-
#-----------------------------------------------------------------------------
|
363
|
-
# Conditional fields based on the status field values
|
364
|
-
# "Risk Accepted" comments, resources
|
365
|
-
# "Ongoing" scheduledCompletionDate, resources, milestones (at least 1)
|
366
|
-
# "Completed" scheduledCompletionDate, comments, resources,
|
367
|
-
# completionDate, milestones (at least 1)
|
368
|
-
# "Not Applicable" POAM can not be created
|
369
|
-
#-----------------------------------------------------------------------------
|
370
|
-
# rubocop:disable Style/CaseLikeIf, Style/StringLiterals
|
371
|
-
if options[:status] == "Risk Accepted"
|
372
|
-
if options[:comments].nil?
|
373
|
-
puts 'When status = "Risk Accepted" the following parameters/fields are required:'.red
|
374
|
-
puts ' comments'.red
|
375
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
376
|
-
exit
|
377
|
-
elsif !(options[:scheduledCompletionDate].nil? && options[:milestone].nil?)
|
378
|
-
puts 'When status = "Risk Accepted" POA&M Item CAN NOT be saved with the following parameters/fields:'.red
|
379
|
-
puts ' scheduledCompletionDate, or milestone'.red
|
380
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
381
|
-
exit
|
382
|
-
else
|
383
|
-
body.comments = options[:comments]
|
384
|
-
end
|
385
|
-
elsif options[:status] == "Ongoing"
|
386
|
-
if options[:scheduledCompletionDate].nil? || options[:milestone].nil?
|
387
|
-
puts 'When status = "Ongoing" the following parameters/fields are required:'.red
|
388
|
-
puts ' scheduledCompletionDate, milestone'.red
|
389
|
-
print_milestone_help
|
390
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
391
|
-
exit
|
392
|
-
elsif options[:milestone]["description"].nil? || options[:milestone]["scheduledCompletionDate"].nil?
|
393
|
-
puts 'Missing milstone parameters/fields'.red
|
394
|
-
print_milestone_help
|
395
|
-
exit
|
396
|
-
else
|
397
|
-
body.scheduled_completion_date = options[:scheduledCompletionDate]
|
398
|
-
|
399
|
-
milestone = EmassClient::MilestonesRequiredPut.new
|
400
|
-
milestone.milestone_id = options[:milestone]["milestoneId"] if options[:milestone]["milestoneId"]
|
401
|
-
milestone.description = options[:milestone]["description"]
|
402
|
-
milestone.scheduled_completion_date = options[:milestone]["scheduledCompletionDate"]
|
403
|
-
milestone_array = Array.new(1, milestone)
|
404
|
-
body.milestones = milestone_array
|
405
|
-
end
|
406
|
-
elsif options[:status] == "Completed"
|
407
|
-
if options[:scheduledCompletionDate].nil? || options[:comments].nil? ||
|
408
|
-
options[:completionDate].nil? || options[:milestone].nil?
|
409
|
-
puts 'Missing one of these parameters/fields:'.red
|
410
|
-
puts ' scheduledCompletionDate, comments, completionDate, or milestone'.red
|
411
|
-
print_milestone_help
|
412
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
413
|
-
exit
|
414
|
-
else
|
415
|
-
body.scheduled_completion_date = options[:scheduledCompletionDate]
|
416
|
-
body.comments = options[:comments]
|
417
|
-
body.completion_date = options[:completionDate]
|
418
|
-
|
419
|
-
milestone = EmassClient::MilestonesRequiredPut.new
|
420
|
-
milestone.milestone_id = options[:milestone]["milestoneId"] if options[:milestone]["milestoneId"]
|
421
|
-
milestone.description = options[:milestone]["description"]
|
422
|
-
milestone.scheduled_completion_date = options[:milestone]["scheduledCompletionDate"]
|
423
|
-
milestone_array = Array.new(1, milestone)
|
424
|
-
body.milestones = milestone_array
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
# POC checks: If any poc information is provided all POC fields are required
|
429
|
-
if options[:pocFirstName]
|
430
|
-
if options[:pocLastName].nil? || options[:pocEmail].nil? || options[:pocPhoneNumber].nil?
|
431
|
-
puts 'If a POC first name is given, then all POC information must be entered:'.red
|
432
|
-
puts ' pocLastName, pocEmail, pocPhoneNumber'.red
|
433
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
434
|
-
exit
|
435
|
-
end
|
436
|
-
elsif options[:pocLastName]
|
437
|
-
if options[:pocFirstName].nil? || options[:pocEmail].nil? || options[:pocPhoneNumber].nil?
|
438
|
-
puts 'If a POC last name is given, then all POC information must be entered:'.red
|
439
|
-
puts ' pocFirstName, pocEmail, pocPhoneNumber'.red
|
440
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
441
|
-
exit
|
442
|
-
end
|
443
|
-
elsif options[:pocEmail]
|
444
|
-
if options[:pocFirstName].nil? || options[:pocLastName].nil? || options[:pocPhoneNumber].nil?
|
445
|
-
puts 'If a POC email is given, then all POC information must be entered:'.red
|
446
|
-
puts ' pocFirstName, pocLastName, pocPhoneNumber'.red
|
447
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
448
|
-
exit
|
449
|
-
end
|
450
|
-
elsif options[:pocPhoneNumber]
|
451
|
-
if options[:pocFirstName].nil? || options[:pocLastName].nil? || options[:pocEmail].nil?
|
452
|
-
puts 'If a POC phone number is given, then all POC information must be entered:'.red
|
453
|
-
puts ' pocFirstName, pocLastName, pocEmail'.red
|
454
|
-
puts POAMS_PUT_HELP_MESSAGE.yellow
|
455
|
-
exit
|
456
|
-
end
|
457
|
-
end
|
458
|
-
# rubocop:enable Style/CaseLikeIf, Style/StringLiterals
|
459
|
-
end
|
460
|
-
|
461
|
-
def print_milestone_help
|
462
|
-
puts 'Milestone format is:'.yellow
|
463
|
-
puts ' --milestone milestoneId:[value] description:"[value]" scheduledCompletionDate:"[value]"'.yellow
|
464
|
-
puts 'The milestoneId:[value] is optional, if not provided a new milestone is created'.yellow
|
465
|
-
end
|
466
|
-
end
|
467
|
-
# rubocop:enable Metrics/AbcSize, Metrics/BlockLength, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
468
|
-
end
|
469
|
-
|
470
|
-
# Update Milestones items to a system.
|
471
|
-
#
|
472
|
-
# Endpoint:
|
473
|
-
# /api/systems/{systemId}/poams/{poamId}/milestones - Update milestones in one or many poa&m items in a system
|
474
|
-
class Milestones < SubCommandBase
|
475
|
-
def self.exit_on_failure?
|
476
|
-
true
|
477
|
-
end
|
478
|
-
|
479
|
-
desc 'update', 'Update milestone(s) for given specified system and poam'
|
480
|
-
long_desc Help.text(:milestone_put_mapper)
|
481
|
-
|
482
|
-
# Required parameters/fields
|
483
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
484
|
-
option :poamId, type: :numeric, required: true, desc: 'A numeric value representing the poam identification'
|
485
|
-
option :milestoneId,
|
486
|
-
type: :numeric, required: true, desc: 'A numeric value representing the milestone identification'
|
487
|
-
option :description, type: :string, required: true, desc: 'The milestone description'
|
488
|
-
option :scheduledCompletionDate,
|
489
|
-
type: :numeric, required: false, desc: 'The scheduled completion date - Unix time format'
|
490
|
-
|
491
|
-
def update
|
492
|
-
body = EmassClient::MilestonesGet.new
|
493
|
-
body.milestone_id = options[:milestoneId]
|
494
|
-
body.description = options[:description]
|
495
|
-
body.scheduled_completion_date = options[:scheduledCompletionDate]
|
496
|
-
body_array = Array.new(1, body)
|
497
|
-
|
498
|
-
begin
|
499
|
-
# Get milestones in one or many poa&m items in a system
|
500
|
-
result = EmassClient::MilestonesApi
|
501
|
-
.new
|
502
|
-
.update_milestone_by_system_id_and_poam_id(options[:systemId], options[:poamId], body_array)
|
503
|
-
puts to_output_hash(result).green
|
504
|
-
rescue EmassClient::ApiError => e
|
505
|
-
puts 'Exception when calling MilestonesApi->update_milestone_by_system_id_and_poam_id'.red
|
506
|
-
puts to_output_hash(e)
|
507
|
-
end
|
508
|
-
end
|
509
|
-
end
|
510
|
-
|
511
|
-
# Update one or many artifacts for a system (this implementation only updates one artifact per each execution)
|
512
|
-
#
|
513
|
-
# Endpoint:
|
514
|
-
# /api/systems/{systemId}/artifacts - Put (update) one or many artifacts for a system
|
515
|
-
class Artifacts < SubCommandBase
|
516
|
-
def self.exit_on_failure?
|
517
|
-
true
|
518
|
-
end
|
519
|
-
|
520
|
-
desc 'update', 'Updates artifacts for a system with provided entries'
|
521
|
-
long_desc Help.text(:artifacts_put_mapper)
|
522
|
-
|
523
|
-
# Required parameters/fields
|
524
|
-
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
525
|
-
option :filename, type: :string, required: true, desc: 'Artifact file name to be updated'
|
526
|
-
option :type,
|
527
|
-
type: :string, required: true,
|
528
|
-
enum: ['Procedure', 'Diagram', 'Policy', 'Labor', 'Document',
|
529
|
-
'Image', 'Other', 'Scan Result', 'Auditor Report']
|
530
|
-
option :category, type: :string, required: true, enum: ['Implementation Guidance', 'Evidence']
|
531
|
-
option :isTemplate, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
|
532
|
-
# NOTE: compress is a required parameter, however Thor does not allow a boolean type to be required because it
|
533
|
-
# automatically creates a --no-isTemplate option for isTemplate=false
|
534
|
-
|
535
|
-
# Optional fields
|
536
|
-
option :description, type: :string, required: false, desc: 'Artifact description'
|
537
|
-
option :refPageNumber, type: :string, required: false, desc: 'Artifact reference page number'
|
538
|
-
option :ccis, type: :string, required: false, desc: 'The system CCIs string numerical value'
|
539
|
-
option :controls,
|
540
|
-
type: :string, required: false,
|
541
|
-
desc: 'Control acronym associated with the artifact. NIST SP 800-53 Revision 4 defined'
|
542
|
-
option :artifactExpirationDate,
|
543
|
-
type: :numeric, required: false, desc: 'Date Artifact expires and requires review - Unix time format'
|
544
|
-
option :lastReviewedDate,
|
545
|
-
type: :numeric, required: false, desc: 'Date Artifact was last reviewed - Unix time format'
|
546
|
-
|
547
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
548
|
-
def update
|
549
|
-
body = EmassClient::ArtifactsGet.new
|
550
|
-
body.filename = options[:filename]
|
551
|
-
body.type = options[:type]
|
552
|
-
body.category = options[:category]
|
553
|
-
body.is_template = options[:isTemplate]
|
554
|
-
# Optional fields
|
555
|
-
body.description = options[:description] if options[:description]
|
556
|
-
body.ref_page_number = options[:refPageNumber] if options[:refPageNumber]
|
557
|
-
body.ccis = options[:ccis] if options[:ccis]
|
558
|
-
body.controls = options[:controls] if options[:controls]
|
559
|
-
body.artifact_expiration_date = options[:artifactExpirationDate] if options[:artifactExpirationDate]
|
560
|
-
body.last_reviewed_date = options[:lastReviewedDate] if options[:lastReviewedDate]
|
561
|
-
|
562
|
-
body_array = Array.new(1, body)
|
563
|
-
|
564
|
-
begin
|
565
|
-
result = EmassClient::ArtifactsApi.new.update_artifact_by_system_id(options[:systemId], body_array)
|
566
|
-
puts to_output_hash(result).green
|
567
|
-
rescue EmassClient::ApiError => e
|
568
|
-
puts 'Exception when calling ArtifactsApi->update_artifact_by_system_id'.red
|
569
|
-
puts to_output_hash(e)
|
570
|
-
end
|
571
|
-
end
|
572
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
573
|
-
end
|
574
|
-
|
575
|
-
class Put < SubCommandBase
|
576
|
-
desc 'controls', 'Update system Controls'
|
577
|
-
subcommand 'controls', Controls
|
578
|
-
|
579
|
-
desc 'poams', 'Update Plan of Action (POA&M) items for a system'
|
580
|
-
subcommand 'poams', Poams
|
581
|
-
|
582
|
-
desc 'milestones', 'Update Milestones items for a system'
|
583
|
-
subcommand 'milestones', Milestones
|
584
|
-
|
585
|
-
desc 'artifacts', 'Put system Artifacts'
|
586
|
-
subcommand 'artifacts', Artifacts
|
587
|
-
end
|
588
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Hack class that properly formats the CLI help
|
4
|
+
class SubCommandBase < Thor
|
5
|
+
include OutputConverters
|
6
|
+
|
7
|
+
# We do not control the method declaration for the banner
|
8
|
+
|
9
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
10
|
+
def self.banner(command, _namespace = nil, subcommand = false)
|
11
|
+
# Use the $thor_runner (declared by the Thor CLI framework)
|
12
|
+
# to properly format the help text of sub-sub-commands.
|
13
|
+
|
14
|
+
# rubocop:disable Style/GlobalVars
|
15
|
+
if ancestors[0].to_s.include? '::Put'
|
16
|
+
"#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
|
17
|
+
else
|
18
|
+
"#{basename} put #{command.formatted_usage(self, $thor_runner, subcommand)}"
|
19
|
+
end
|
20
|
+
# rubocop:enable Style/GlobalVars
|
21
|
+
end
|
22
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
23
|
+
end
|
24
|
+
|
25
|
+
# Override thor's long_desc identation behavior
|
26
|
+
class Thor
|
27
|
+
module Shell
|
28
|
+
class Basic
|
29
|
+
def print_wrapped(message, _options = {})
|
30
|
+
message = "\n#{message}\n" unless message[0] == "\n"
|
31
|
+
stdout.puts message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module Emasser
|
38
|
+
CONTROLS_PUT_HELP_MESSAGE = "\nInvoke \"bundle exec exe/emasser put controls help update\" for additional help"
|
39
|
+
POAMS_PUT_HELP_MESSAGE = "\nInvoke \"bundle exec exe/emasser put poams help add\" for additional help"
|
40
|
+
# Update Security Control information of a system for both the Implementation Plan and Risk Assessment.
|
41
|
+
#
|
42
|
+
# Endpoint:
|
43
|
+
# /api/systems/{systemId}/controls - Update control information in a system for one or many controls
|
44
|
+
# rubocop:disable Style/WordArray
|
45
|
+
class Controls < SubCommandBase
|
46
|
+
def self.exit_on_failure?
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'update', 'Get control information in a system for one or many controls (acronym)'
|
51
|
+
long_desc Help.text(:controls_put_mapper)
|
52
|
+
|
53
|
+
# Required parameters/fields
|
54
|
+
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
55
|
+
option :acronym, type: :string, required: true, desc: 'The system acronym(s) e.g "AC-1, AC-2"'
|
56
|
+
option :responsibleEntities, type: :string, required: true,
|
57
|
+
desc: 'Description of the responsible entities for the Security Control'
|
58
|
+
option :controlDesignation, type: :string, required: true,
|
59
|
+
enum: ['Common', 'System-Specific', 'Hybrid'],
|
60
|
+
desc: 'The Security Control Designation'
|
61
|
+
option :estimatedCompletionDate, type: :numeric, required: true, desc: 'Estimated completion date, Unix time format'
|
62
|
+
option :implementationNarrative, type: :string, required: true, desc: 'Security control comments'
|
63
|
+
|
64
|
+
# Conditional parameters/fields
|
65
|
+
option :commonControlProvider,
|
66
|
+
type: :string,
|
67
|
+
required: false,
|
68
|
+
enum: ['DoD', 'Component', 'Enclave'],
|
69
|
+
desc: 'Indicate the type of Common Control Provider for an "Inherited" Security Control'
|
70
|
+
option :naJustification,
|
71
|
+
type: :string, required: false,
|
72
|
+
desc: 'Provide justification for Security Controls deemed Not Applicable to the system'
|
73
|
+
option :slcmCriticality,
|
74
|
+
type: :string, required: false,
|
75
|
+
desc: 'Criticality of Security Control regarding SLCM'
|
76
|
+
option :slcmFrequency,
|
77
|
+
type: :string, required: false,
|
78
|
+
enum: ['Constantly', 'Daily', 'Weekly', 'Monthly', 'Quarterly', 'Semi-Annually',
|
79
|
+
'Annually', 'Every Two Years', 'Every Three Years', 'Undetermined'],
|
80
|
+
desc: 'The System-Level Continuous Monitoring frequency'
|
81
|
+
option :slcmMethod,
|
82
|
+
type: :string, required: false,
|
83
|
+
enum: ['Automated', 'Semi-Automated', 'Manual', 'Undetermined'],
|
84
|
+
desc: 'The System-Level Continuous Monitoring method'
|
85
|
+
option :slcmReporting,
|
86
|
+
type: :string, required: false,
|
87
|
+
desc: 'The System-Level Continuous Monitoring reporting'
|
88
|
+
option :slcmTracking,
|
89
|
+
type: :string, required: false,
|
90
|
+
desc: 'The System-Level Continuous Monitoring tracking'
|
91
|
+
option :slcmComments,
|
92
|
+
type: :string, required: false,
|
93
|
+
desc: 'Additional comments for Security Control regarding SLCM'
|
94
|
+
|
95
|
+
# Optional parameters/fields
|
96
|
+
option :implementationStatus,
|
97
|
+
type: :string, required: false,
|
98
|
+
enum: ['Planned', 'Implemented', 'Inherited', 'Not Applicable', 'Manually Inherited'],
|
99
|
+
desc: 'Implementation status of the security control for the information system'
|
100
|
+
option :severity,
|
101
|
+
type: :string, required: false,
|
102
|
+
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
103
|
+
desc: 'The security control severity, required for approved items'
|
104
|
+
option :vulnerabiltySummary, type: :string, required: false, desc: 'The security control vulnerability summary'
|
105
|
+
option :recommendations, type: :string, required: false, desc: 'The security control vulnerability recommendation'
|
106
|
+
option :relevanceOfThreat,
|
107
|
+
type: :string, required: false,
|
108
|
+
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
109
|
+
desc: 'The security control vulnerability of threat'
|
110
|
+
option :likelihood,
|
111
|
+
type: :string, required: false,
|
112
|
+
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
113
|
+
desc: 'The security control likelihood of vulnerability to threats'
|
114
|
+
option :impact,
|
115
|
+
type: :string, required: false,
|
116
|
+
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
117
|
+
desc: 'The security control vulnerability impact'
|
118
|
+
option :impactDescription, type: :string, required: false, desc: 'Description of the security control impact'
|
119
|
+
option :residualRiskLevel,
|
120
|
+
type: :string, required: false,
|
121
|
+
enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High'],
|
122
|
+
desc: 'The security control risk level'
|
123
|
+
option :testMethod,
|
124
|
+
type: :string, required: false,
|
125
|
+
enum: ['Test', 'Interview', 'Examine', 'Test, Interview', 'Test, Examine',
|
126
|
+
'Interview, Examine', 'Test, Interview, Examine'],
|
127
|
+
desc: 'Assessment method/combination that determines if the security requirements are implemented correctly'
|
128
|
+
|
129
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
130
|
+
def update
|
131
|
+
# Required fields
|
132
|
+
body = EmassClient::ControlsGet.new
|
133
|
+
body.acronym = options[:acronym]
|
134
|
+
body.responsible_entities = options[:responsibleEntities]
|
135
|
+
body.control_designation = options[:controlDesignation]
|
136
|
+
body.estimated_completion_date = options[:estimatedCompletionDate]
|
137
|
+
body.implementation_narrative = options[:implementationNarrative]
|
138
|
+
|
139
|
+
process_business_logic(body)
|
140
|
+
|
141
|
+
# Add optional fields
|
142
|
+
body.severity = options[:severity] if options[:severity]
|
143
|
+
body.vulnerabilty_summary = options[:vulnerabiltySummary] if options[:vulnerabiltySummary]
|
144
|
+
body.recommendations = options[:recommendations] if options[:recommendations]
|
145
|
+
body.relevance_of_threat = options[:relevanceOfThreat] if options[:relevanceOfThreat]
|
146
|
+
body.likelihood = options[:likelihood] if options[:likelihood]
|
147
|
+
body.impact = options[:impact] if options[:impact]
|
148
|
+
body.impact_description = options[:impactDescription] if options[:impactDescription]
|
149
|
+
body.residual_risk_level = options[:residualRiskLevel] if options[:residualRiskLevel]
|
150
|
+
body.test_method = options[:testMethod] if options[:testMethod]
|
151
|
+
|
152
|
+
body_array = Array.new(1, body)
|
153
|
+
|
154
|
+
begin
|
155
|
+
result = EmassClient::ControlsApi.new.update_control_by_system_id(options[:systemId], body_array)
|
156
|
+
puts to_output_hash(result).green
|
157
|
+
rescue EmassClient::ApiError => e
|
158
|
+
puts 'Exception when calling ControlsApi->update_control_by_system_id'.red
|
159
|
+
puts to_output_hash(e)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
163
|
+
|
164
|
+
# rubocop:disable Style/CaseLikeIf, Style/StringLiterals, Metrics/BlockLength, Metrics/CyclomaticComplexity
|
165
|
+
no_commands do
|
166
|
+
# rubocop:disable Metrics/PerceivedComplexity, Style/GuardClause
|
167
|
+
def process_business_logic(body)
|
168
|
+
# Conditional fields based on implementationStatus content
|
169
|
+
# unless executes code if conditional is false
|
170
|
+
unless options[:implementationStatus].nil?
|
171
|
+
body.implementation_status = options[:implementationStatus]
|
172
|
+
|
173
|
+
if options[:implementationStatus] == "Planned" || options[:implementationStatus] == "Implemented"
|
174
|
+
if options[:responsibleEntities].nil? || options[:slcmCriticality].nil? ||
|
175
|
+
options[:slcmFrequency].nil? || options[:slcmMethod].nil? ||
|
176
|
+
options[:slcmReporting].nil? || options[:slcmTracking].nil? || options[:slcmComments].nil?
|
177
|
+
puts 'Missing one of these parameters/fields:'.red
|
178
|
+
puts ' responsibleEntities, slcmCriticality, slcmFrequency,'.red
|
179
|
+
puts ' slcmMethod,slcmReporting, slcmTracking, slcmComments'.red
|
180
|
+
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
181
|
+
exit
|
182
|
+
else
|
183
|
+
body.responsible_entities = options[:responsibleEntities]
|
184
|
+
body.slcm_criticality = options[:slcmCriticality]
|
185
|
+
body.slcm_frequency = options[:slcmFrequency]
|
186
|
+
body.slcm_method = options[:slcmMethod]
|
187
|
+
body.slcm_reporting = options[:slcmReporting]
|
188
|
+
body.slcm_tracking = options[:slcmTracking]
|
189
|
+
body.slcm_comments = options[:slcmComments]
|
190
|
+
end
|
191
|
+
elsif options[:implementationStatus] == 'Not Applicable'
|
192
|
+
if options[:naJustification].nil? || options[:responsibleEntities].nil?
|
193
|
+
puts 'Missing one of these parameters/fields:'.red
|
194
|
+
puts ' naJustification, responsibleEntities'.red
|
195
|
+
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
196
|
+
exit
|
197
|
+
else
|
198
|
+
body.slcm_reporting = options[:naJustification]
|
199
|
+
body.responsible_entities = options[:responsibleEntities]
|
200
|
+
end
|
201
|
+
elsif options[:implementationStatus] == 'Manually Inherited'
|
202
|
+
if options[:commonControlProvider].nil? || options[:responsibleEntities].nil? ||
|
203
|
+
options[:slcmCriticality].nil? || options[:slcmFrequency].nil? || options[:slcmMethod].nil? ||
|
204
|
+
options[:slcmReporting].nil? || options[:slcmTracking].nil? || options[:slcmComments].nil?
|
205
|
+
puts 'Missing one of these parameters/fields:'.red
|
206
|
+
puts ' commonControlProvider, responsibleEntities, slcmCriticality,'.red
|
207
|
+
puts ' slcmFrequency, slcmMethod, slcmReporting, slcmTracking, slcmComments'.red
|
208
|
+
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
209
|
+
exit
|
210
|
+
else
|
211
|
+
body.common_control_provider = options[:commonControlProvider]
|
212
|
+
body.responsible_entities = options[:responsibleEntities]
|
213
|
+
body.slcm_criticality = options[:slcmCriticality]
|
214
|
+
body.slcm_frequency = options[:slcmFrequency]
|
215
|
+
body.slcm_method = options[:slcmMethod]
|
216
|
+
body.slcm_reporting = options[:slcmReporting]
|
217
|
+
body.slcm_tracking = options[:slcmTracking]
|
218
|
+
body.slcm_comments = options[:slcmComments]
|
219
|
+
end
|
220
|
+
elsif options[:implementationStatus] == 'Inherited'
|
221
|
+
if options[:commonControlProvider].nil?
|
222
|
+
puts 'When implementationStatus value is "Inherited" only the following fields are updated:'.red
|
223
|
+
puts ' controlDesignation and commonControlProvider'.red
|
224
|
+
puts 'Missing the commonControlProvider field'.red
|
225
|
+
puts CONTROLS_PUT_HELP_MESSAGE.yellow
|
226
|
+
exit
|
227
|
+
else
|
228
|
+
body.common_control_provider = options[:commonControlProvider]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
# rubocop:enable Metrics/PerceivedComplexity, Style/GuardClause
|
234
|
+
end
|
235
|
+
# rubocop:enable Style/CaseLikeIf, Style/StringLiterals, Metrics/BlockLength, Metrics/CyclomaticComplexity
|
236
|
+
end
|
237
|
+
# rubocop:enable Style/WordArray
|
238
|
+
|
239
|
+
# Update Plan of Action (POA&M) items to a system.
|
240
|
+
#
|
241
|
+
# Endpoint:
|
242
|
+
# /api/systems/{systemId}/poams - Update one or many poa&m items in a system
|
243
|
+
class Poams < SubCommandBase
|
244
|
+
def self.exit_on_failure?
|
245
|
+
true
|
246
|
+
end
|
247
|
+
|
248
|
+
# Update a POAM -----------------------------------------------------------
|
249
|
+
#
|
250
|
+
# The following fields are required based on the contents of the status field
|
251
|
+
# status Required Fields
|
252
|
+
# -------------------------------------------------------------------------
|
253
|
+
# Risk Accepted comments, resources
|
254
|
+
# Ongoing scheduledCompletionDate, resources, milestones (at least 1)
|
255
|
+
# Completed scheduledCompletionDate, comments, resources,
|
256
|
+
# completionDate, milestones (at least 1)
|
257
|
+
# Not Applicable POAM can not be created
|
258
|
+
#--------------------------------------------------------------------------
|
259
|
+
#
|
260
|
+
# If a POC email is supplied, the application will attempt to locate a user
|
261
|
+
# already registered within the application and pre-populate any information
|
262
|
+
# not explicitly supplied in the request. If no such user is found, these
|
263
|
+
# fields are required within the request.
|
264
|
+
# pocOrganization, pocFirstName, pocLastName, pocEmail, pocPhoneNumber
|
265
|
+
|
266
|
+
desc 'update', 'Update one or many POA&M items in a system'
|
267
|
+
long_desc Help.text(:poam_put_mapper)
|
268
|
+
|
269
|
+
# Required parameters/fields
|
270
|
+
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
271
|
+
option :poamId, type: :numeric, required: true, desc: 'A numeric value representing the poam identification'
|
272
|
+
# option :displayPoamId,
|
273
|
+
# type: :numeric, required: true,
|
274
|
+
# desc: 'Globally unique identifier for individual POA&M Items, seen on the front-end as "ID"'
|
275
|
+
option :status, type: :string, required: true, enum: ['Ongoing', 'Risk Accepted', 'Completed', 'Not Applicable']
|
276
|
+
option :vulnerabilityDescription, type: :string, required: true, desc: 'POA&M vulnerability description'
|
277
|
+
option :sourceIdentVuln,
|
278
|
+
type: :string, required: true, desc: 'Source that identifies the vulnerability'
|
279
|
+
option :pocOrganization, type: :string, required: true, desc: 'Organization/Office represented'
|
280
|
+
option :resources, type: :string, required: true, desc: 'List of resources used'
|
281
|
+
|
282
|
+
# Conditional parameters/fields
|
283
|
+
option :milestone,
|
284
|
+
type: :hash, required: false, desc: 'key:values are: milestoneId, description and scheduledCompletionDate'
|
285
|
+
option :pocFirstName, type: :string, required: false, desc: 'First name of POC'
|
286
|
+
option :pocLastName, type: :string, required: false, desc: 'Last name of POC.'
|
287
|
+
option :pocEmail, type: :string, required: false, desc: 'Email address of POC'
|
288
|
+
option :pocPhoneNumber, type: :string, required: false, desc: 'Phone number of POC (area code) ***-**** format'
|
289
|
+
option :severity, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
290
|
+
option :scheduledCompletionDate,
|
291
|
+
type: :numeric, required: false, desc: 'The scheduled completion date - Unix time format'
|
292
|
+
option :completionDate,
|
293
|
+
type: :numeric, required: false, desc: 'The schedule completion date - Unix time format'
|
294
|
+
option :comments, type: :string, required: false, desc: 'Comments for completed and risk accepted POA&M items'
|
295
|
+
option :isActive, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
|
296
|
+
|
297
|
+
# Optional parameters/fields
|
298
|
+
option :externalUid, type: :string, required: false, desc: 'External ID associated with the POA&M'
|
299
|
+
option :controlAcronym, type: :string, required: false, desc: 'The system acronym(s) e.g "AC-1, AC-2"'
|
300
|
+
option :cci, type: :string, required: false, desc: 'The system CCIS string numerical value'
|
301
|
+
option :securityChecks, type: :string, required: false, desc: 'Security Checks that are associated with the POA&M'
|
302
|
+
option :rawSeverity, type: :string, required: false, enum: %w[I II III]
|
303
|
+
option :relevanceOfThreat,
|
304
|
+
type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
305
|
+
option :likelihood, type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
306
|
+
option :impact, type: :string, required: false, desc: 'Description of Security Control’s impact'
|
307
|
+
option :impactDescription, type: :string, required: false, desc: 'Description of the security control impact'
|
308
|
+
option :residualRiskLevel,
|
309
|
+
type: :string, required: false, enum: ['Very Low', 'Low', 'Moderate', 'High', 'Very High']
|
310
|
+
option :recommendations, type: :string, required: false, desc: 'Recomendations'
|
311
|
+
option :mitigation, type: :string, required: false, desc: 'Mitigation explanation'
|
312
|
+
|
313
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
314
|
+
def update
|
315
|
+
# Required fields
|
316
|
+
body = EmassClient::PoamGet.new
|
317
|
+
body.poam_id = options[:poamId]
|
318
|
+
body.status = options[:status]
|
319
|
+
body.vulnerability_description = options[:vulnerabilityDescription]
|
320
|
+
body.source_ident_vuln = options[:sourceIdentVuln]
|
321
|
+
body.poc_organization = options[:pocOrganization]
|
322
|
+
body.resources = options[:resources]
|
323
|
+
|
324
|
+
process_business_logic(body)
|
325
|
+
|
326
|
+
# Add conditional fields
|
327
|
+
body.poc_first_name = options[:pocFirstName] if options[:pocFirstName]
|
328
|
+
body.poc_last_name = options[:pocLastName] if options[:pocLastName]
|
329
|
+
body.poc_email = options[:pocEmail] if options[:pocEmail]
|
330
|
+
body.poc_phone_number = options[:pocPhoneNumber] if options[:pocPhoneNumber]
|
331
|
+
body.severity = options[:severity] if options[:severity]
|
332
|
+
|
333
|
+
# Add optional fields
|
334
|
+
body.external_uid = options[:externalUid] if options[:externalUid]
|
335
|
+
body.control_acronym = options[:controlAcronym] if options[:controlAcronym]
|
336
|
+
body.cci = options[:cci] if options[:cci]
|
337
|
+
body.security_checks = options[:securityChecks] if options[:securityChecks]
|
338
|
+
body.raw_severity = options[:rawSeverity] if options[:rawSeverity]
|
339
|
+
body.relevance_of_threat = options[:relevanceOfThreat] if options[:relevanceOfThreat]
|
340
|
+
body.likelihood = options[:likelihood] if options[:likelihood]
|
341
|
+
body.impact = options[:impact] if options[:impact]
|
342
|
+
body.impact_description = options[:impactDescription] if options[:impactDescription]
|
343
|
+
body.residual_risk_level = options[:residualRiskLevel] if options[:residualRiskLevel]
|
344
|
+
body.recommendations = options[:recommendations] if options[:recommendations]
|
345
|
+
body.mitigation = options[:mitigation] if options[:mitigation]
|
346
|
+
|
347
|
+
body_array = Array.new(1, body)
|
348
|
+
|
349
|
+
begin
|
350
|
+
result = EmassClient::POAMApi.new.update_poam_by_system_id(options[:systemId], body_array)
|
351
|
+
puts to_output_hash(result).green
|
352
|
+
rescue EmassClient::ApiError => e
|
353
|
+
puts 'Exception when calling POAMApi->update_poam_by_system_id'.red
|
354
|
+
puts to_output_hash(e)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
358
|
+
|
359
|
+
# rubocop:disable Metrics/AbcSize, Metrics/BlockLength, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
360
|
+
no_commands do
|
361
|
+
def process_business_logic(body)
|
362
|
+
#-----------------------------------------------------------------------------
|
363
|
+
# Conditional fields based on the status field values
|
364
|
+
# "Risk Accepted" comments, resources
|
365
|
+
# "Ongoing" scheduledCompletionDate, resources, milestones (at least 1)
|
366
|
+
# "Completed" scheduledCompletionDate, comments, resources,
|
367
|
+
# completionDate, milestones (at least 1)
|
368
|
+
# "Not Applicable" POAM can not be created
|
369
|
+
#-----------------------------------------------------------------------------
|
370
|
+
# rubocop:disable Style/CaseLikeIf, Style/StringLiterals
|
371
|
+
if options[:status] == "Risk Accepted"
|
372
|
+
if options[:comments].nil?
|
373
|
+
puts 'When status = "Risk Accepted" the following parameters/fields are required:'.red
|
374
|
+
puts ' comments'.red
|
375
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
376
|
+
exit
|
377
|
+
elsif !(options[:scheduledCompletionDate].nil? && options[:milestone].nil?)
|
378
|
+
puts 'When status = "Risk Accepted" POA&M Item CAN NOT be saved with the following parameters/fields:'.red
|
379
|
+
puts ' scheduledCompletionDate, or milestone'.red
|
380
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
381
|
+
exit
|
382
|
+
else
|
383
|
+
body.comments = options[:comments]
|
384
|
+
end
|
385
|
+
elsif options[:status] == "Ongoing"
|
386
|
+
if options[:scheduledCompletionDate].nil? || options[:milestone].nil?
|
387
|
+
puts 'When status = "Ongoing" the following parameters/fields are required:'.red
|
388
|
+
puts ' scheduledCompletionDate, milestone'.red
|
389
|
+
print_milestone_help
|
390
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
391
|
+
exit
|
392
|
+
elsif options[:milestone]["description"].nil? || options[:milestone]["scheduledCompletionDate"].nil?
|
393
|
+
puts 'Missing milstone parameters/fields'.red
|
394
|
+
print_milestone_help
|
395
|
+
exit
|
396
|
+
else
|
397
|
+
body.scheduled_completion_date = options[:scheduledCompletionDate]
|
398
|
+
|
399
|
+
milestone = EmassClient::MilestonesRequiredPut.new
|
400
|
+
milestone.milestone_id = options[:milestone]["milestoneId"] if options[:milestone]["milestoneId"]
|
401
|
+
milestone.description = options[:milestone]["description"]
|
402
|
+
milestone.scheduled_completion_date = options[:milestone]["scheduledCompletionDate"]
|
403
|
+
milestone_array = Array.new(1, milestone)
|
404
|
+
body.milestones = milestone_array
|
405
|
+
end
|
406
|
+
elsif options[:status] == "Completed"
|
407
|
+
if options[:scheduledCompletionDate].nil? || options[:comments].nil? ||
|
408
|
+
options[:completionDate].nil? || options[:milestone].nil?
|
409
|
+
puts 'Missing one of these parameters/fields:'.red
|
410
|
+
puts ' scheduledCompletionDate, comments, completionDate, or milestone'.red
|
411
|
+
print_milestone_help
|
412
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
413
|
+
exit
|
414
|
+
else
|
415
|
+
body.scheduled_completion_date = options[:scheduledCompletionDate]
|
416
|
+
body.comments = options[:comments]
|
417
|
+
body.completion_date = options[:completionDate]
|
418
|
+
|
419
|
+
milestone = EmassClient::MilestonesRequiredPut.new
|
420
|
+
milestone.milestone_id = options[:milestone]["milestoneId"] if options[:milestone]["milestoneId"]
|
421
|
+
milestone.description = options[:milestone]["description"]
|
422
|
+
milestone.scheduled_completion_date = options[:milestone]["scheduledCompletionDate"]
|
423
|
+
milestone_array = Array.new(1, milestone)
|
424
|
+
body.milestones = milestone_array
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
# POC checks: If any poc information is provided all POC fields are required
|
429
|
+
if options[:pocFirstName]
|
430
|
+
if options[:pocLastName].nil? || options[:pocEmail].nil? || options[:pocPhoneNumber].nil?
|
431
|
+
puts 'If a POC first name is given, then all POC information must be entered:'.red
|
432
|
+
puts ' pocLastName, pocEmail, pocPhoneNumber'.red
|
433
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
434
|
+
exit
|
435
|
+
end
|
436
|
+
elsif options[:pocLastName]
|
437
|
+
if options[:pocFirstName].nil? || options[:pocEmail].nil? || options[:pocPhoneNumber].nil?
|
438
|
+
puts 'If a POC last name is given, then all POC information must be entered:'.red
|
439
|
+
puts ' pocFirstName, pocEmail, pocPhoneNumber'.red
|
440
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
441
|
+
exit
|
442
|
+
end
|
443
|
+
elsif options[:pocEmail]
|
444
|
+
if options[:pocFirstName].nil? || options[:pocLastName].nil? || options[:pocPhoneNumber].nil?
|
445
|
+
puts 'If a POC email is given, then all POC information must be entered:'.red
|
446
|
+
puts ' pocFirstName, pocLastName, pocPhoneNumber'.red
|
447
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
448
|
+
exit
|
449
|
+
end
|
450
|
+
elsif options[:pocPhoneNumber]
|
451
|
+
if options[:pocFirstName].nil? || options[:pocLastName].nil? || options[:pocEmail].nil?
|
452
|
+
puts 'If a POC phone number is given, then all POC information must be entered:'.red
|
453
|
+
puts ' pocFirstName, pocLastName, pocEmail'.red
|
454
|
+
puts POAMS_PUT_HELP_MESSAGE.yellow
|
455
|
+
exit
|
456
|
+
end
|
457
|
+
end
|
458
|
+
# rubocop:enable Style/CaseLikeIf, Style/StringLiterals
|
459
|
+
end
|
460
|
+
|
461
|
+
def print_milestone_help
|
462
|
+
puts 'Milestone format is:'.yellow
|
463
|
+
puts ' --milestone milestoneId:[value] description:"[value]" scheduledCompletionDate:"[value]"'.yellow
|
464
|
+
puts 'The milestoneId:[value] is optional, if not provided a new milestone is created'.yellow
|
465
|
+
end
|
466
|
+
end
|
467
|
+
# rubocop:enable Metrics/AbcSize, Metrics/BlockLength, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
468
|
+
end
|
469
|
+
|
470
|
+
# Update Milestones items to a system.
|
471
|
+
#
|
472
|
+
# Endpoint:
|
473
|
+
# /api/systems/{systemId}/poams/{poamId}/milestones - Update milestones in one or many poa&m items in a system
|
474
|
+
class Milestones < SubCommandBase
|
475
|
+
def self.exit_on_failure?
|
476
|
+
true
|
477
|
+
end
|
478
|
+
|
479
|
+
desc 'update', 'Update milestone(s) for given specified system and poam'
|
480
|
+
long_desc Help.text(:milestone_put_mapper)
|
481
|
+
|
482
|
+
# Required parameters/fields
|
483
|
+
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
484
|
+
option :poamId, type: :numeric, required: true, desc: 'A numeric value representing the poam identification'
|
485
|
+
option :milestoneId,
|
486
|
+
type: :numeric, required: true, desc: 'A numeric value representing the milestone identification'
|
487
|
+
option :description, type: :string, required: true, desc: 'The milestone description'
|
488
|
+
option :scheduledCompletionDate,
|
489
|
+
type: :numeric, required: false, desc: 'The scheduled completion date - Unix time format'
|
490
|
+
|
491
|
+
def update
|
492
|
+
body = EmassClient::MilestonesGet.new
|
493
|
+
body.milestone_id = options[:milestoneId]
|
494
|
+
body.description = options[:description]
|
495
|
+
body.scheduled_completion_date = options[:scheduledCompletionDate]
|
496
|
+
body_array = Array.new(1, body)
|
497
|
+
|
498
|
+
begin
|
499
|
+
# Get milestones in one or many poa&m items in a system
|
500
|
+
result = EmassClient::MilestonesApi
|
501
|
+
.new
|
502
|
+
.update_milestone_by_system_id_and_poam_id(options[:systemId], options[:poamId], body_array)
|
503
|
+
puts to_output_hash(result).green
|
504
|
+
rescue EmassClient::ApiError => e
|
505
|
+
puts 'Exception when calling MilestonesApi->update_milestone_by_system_id_and_poam_id'.red
|
506
|
+
puts to_output_hash(e)
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
# Update one or many artifacts for a system (this implementation only updates one artifact per each execution)
|
512
|
+
#
|
513
|
+
# Endpoint:
|
514
|
+
# /api/systems/{systemId}/artifacts - Put (update) one or many artifacts for a system
|
515
|
+
class Artifacts < SubCommandBase
|
516
|
+
def self.exit_on_failure?
|
517
|
+
true
|
518
|
+
end
|
519
|
+
|
520
|
+
desc 'update', 'Updates artifacts for a system with provided entries'
|
521
|
+
long_desc Help.text(:artifacts_put_mapper)
|
522
|
+
|
523
|
+
# Required parameters/fields
|
524
|
+
option :systemId, type: :numeric, required: true, desc: 'A numeric value representing the system identification'
|
525
|
+
option :filename, type: :string, required: true, desc: 'Artifact file name to be updated'
|
526
|
+
option :type,
|
527
|
+
type: :string, required: true,
|
528
|
+
enum: ['Procedure', 'Diagram', 'Policy', 'Labor', 'Document',
|
529
|
+
'Image', 'Other', 'Scan Result', 'Auditor Report']
|
530
|
+
option :category, type: :string, required: true, enum: ['Implementation Guidance', 'Evidence']
|
531
|
+
option :isTemplate, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
|
532
|
+
# NOTE: compress is a required parameter, however Thor does not allow a boolean type to be required because it
|
533
|
+
# automatically creates a --no-isTemplate option for isTemplate=false
|
534
|
+
|
535
|
+
# Optional fields
|
536
|
+
option :description, type: :string, required: false, desc: 'Artifact description'
|
537
|
+
option :refPageNumber, type: :string, required: false, desc: 'Artifact reference page number'
|
538
|
+
option :ccis, type: :string, required: false, desc: 'The system CCIs string numerical value'
|
539
|
+
option :controls,
|
540
|
+
type: :string, required: false,
|
541
|
+
desc: 'Control acronym associated with the artifact. NIST SP 800-53 Revision 4 defined'
|
542
|
+
option :artifactExpirationDate,
|
543
|
+
type: :numeric, required: false, desc: 'Date Artifact expires and requires review - Unix time format'
|
544
|
+
option :lastReviewedDate,
|
545
|
+
type: :numeric, required: false, desc: 'Date Artifact was last reviewed - Unix time format'
|
546
|
+
|
547
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
548
|
+
def update
|
549
|
+
body = EmassClient::ArtifactsGet.new
|
550
|
+
body.filename = options[:filename]
|
551
|
+
body.type = options[:type]
|
552
|
+
body.category = options[:category]
|
553
|
+
body.is_template = options[:isTemplate]
|
554
|
+
# Optional fields
|
555
|
+
body.description = options[:description] if options[:description]
|
556
|
+
body.ref_page_number = options[:refPageNumber] if options[:refPageNumber]
|
557
|
+
body.ccis = options[:ccis] if options[:ccis]
|
558
|
+
body.controls = options[:controls] if options[:controls]
|
559
|
+
body.artifact_expiration_date = options[:artifactExpirationDate] if options[:artifactExpirationDate]
|
560
|
+
body.last_reviewed_date = options[:lastReviewedDate] if options[:lastReviewedDate]
|
561
|
+
|
562
|
+
body_array = Array.new(1, body)
|
563
|
+
|
564
|
+
begin
|
565
|
+
result = EmassClient::ArtifactsApi.new.update_artifact_by_system_id(options[:systemId], body_array)
|
566
|
+
puts to_output_hash(result).green
|
567
|
+
rescue EmassClient::ApiError => e
|
568
|
+
puts 'Exception when calling ArtifactsApi->update_artifact_by_system_id'.red
|
569
|
+
puts to_output_hash(e)
|
570
|
+
end
|
571
|
+
end
|
572
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
573
|
+
end
|
574
|
+
|
575
|
+
class Put < SubCommandBase
|
576
|
+
desc 'controls', 'Update system Controls'
|
577
|
+
subcommand 'controls', Controls
|
578
|
+
|
579
|
+
desc 'poams', 'Update Plan of Action (POA&M) items for a system'
|
580
|
+
subcommand 'poams', Poams
|
581
|
+
|
582
|
+
desc 'milestones', 'Update Milestones items for a system'
|
583
|
+
subcommand 'milestones', Milestones
|
584
|
+
|
585
|
+
desc 'artifacts', 'Put system Artifacts'
|
586
|
+
subcommand 'artifacts', Artifacts
|
587
|
+
end
|
588
|
+
end
|