emasser 1.0.3 → 1.0.6

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.env-example +2 -0
  3. data/.github/workflows/gh-pages.yml +4 -5
  4. data/.github/workflows/release.yml +9 -9
  5. data/Dockerfile +6 -4
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +23 -30
  8. data/README.md +87 -78
  9. data/docs/features.md +343 -207
  10. data/docs/images/emasser_architecture.jpg +0 -0
  11. data/emasser.gemspec +5 -3
  12. data/images/emasser_architecture.jpg +0 -0
  13. data/images/emasser_diagram-Page-3.jpg +0 -0
  14. data/lib/emasser/cli.rb +2 -2
  15. data/lib/emasser/configuration.rb +1 -0
  16. data/lib/emasser/constants.rb +11 -3
  17. data/lib/emasser/delete.rb +9 -7
  18. data/lib/emasser/get.rb +43 -48
  19. data/lib/emasser/help/cloudresource_post_mapper.md +62 -0
  20. data/lib/emasser/help/container_post_mapper.md +44 -0
  21. data/lib/emasser/output_converters.rb +101 -4
  22. data/lib/emasser/post.rb +231 -38
  23. data/lib/emasser/put.rb +23 -16
  24. data/lib/emasser/version.rb +1 -1
  25. metadata +19 -25
  26. data/.github/workflows/generate_docs.yml +0 -33
  27. data/docs/developers.md +0 -115
  28. data/docs/swagger/dist/favicon-16x16.png +0 -0
  29. data/docs/swagger/dist/favicon-32x32.png +0 -0
  30. data/docs/swagger/dist/oauth2-redirect.html +0 -75
  31. data/docs/swagger/dist/swagger-ui-bundle.js +0 -3
  32. data/docs/swagger/dist/swagger-ui-bundle.js.map +0 -1
  33. data/docs/swagger/dist/swagger-ui-es-bundle-core.js +0 -3
  34. data/docs/swagger/dist/swagger-ui-es-bundle-core.js.map +0 -1
  35. data/docs/swagger/dist/swagger-ui-es-bundle.js +0 -3
  36. data/docs/swagger/dist/swagger-ui-es-bundle.js.map +0 -1
  37. data/docs/swagger/dist/swagger-ui-standalone-preset.js +0 -3
  38. data/docs/swagger/dist/swagger-ui-standalone-preset.js.map +0 -1
  39. data/docs/swagger/dist/swagger-ui.css +0 -4
  40. data/docs/swagger/dist/swagger-ui.css.map +0 -1
  41. data/docs/swagger/dist/swagger-ui.js +0 -3
  42. data/docs/swagger/dist/swagger-ui.js.map +0 -1
  43. data/docs/swagger/index.html +0 -60
data/emasser.gemspec CHANGED
@@ -6,11 +6,11 @@ Gem::Specification.new do |spec|
6
6
  spec.name = 'emasser'
7
7
  spec.version = Emasser::VERSION
8
8
  spec.authors = ['Amndeep Singh Mann', 'George Dias', 'Kyle Fagan', 'Robert Clark', 'Aaron Lippold']
9
- spec.email = ['saf@mitre.org']
9
+ spec.email = ['saf@groups.mitre.org']
10
10
  spec.licenses = ['Apache-2.0']
11
11
 
12
12
  spec.summary = 'Provide an automated capability for invoving eMASS API endpoints'
13
- spec.description = 'emasser can be used as a gem or used from the command line to access eMASS via thei API.'
13
+ spec.description = 'emasser can be used as a gem or used from the command line (CL) to access eMASS endpoints via their API.'
14
14
  spec.homepage = 'https://saf.mitre.org'
15
15
  spec.required_ruby_version = Gem::Requirement.new('~> 2.5')
16
16
 
@@ -21,13 +21,15 @@ Gem::Specification.new do |spec|
21
21
  end
22
22
  spec.bindir = 'exe'
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ # References: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-rubygems-registry
25
+ spec.metadata = { "github_repo" => "ssh://github.com/mitre/emasser" }
24
26
 
25
27
  spec.add_runtime_dependency 'activesupport', '~> 6.1.4'
26
28
  spec.add_runtime_dependency 'colorize', '~> 0.8.1'
27
29
  spec.add_runtime_dependency 'dotenv', '~> 2.7.6'
28
30
  spec.add_runtime_dependency 'rubyzip', '~> 2.3.2'
29
31
  spec.add_runtime_dependency 'thor', '~> 1.1.0'
30
- spec.add_runtime_dependency 'emass_client', '~> 1.0'
32
+ spec.add_runtime_dependency 'emass_client', '~> 1.0', '!= 1.0.3'
31
33
 
32
34
  spec.add_development_dependency 'bundler', '~> 2.3'
33
35
  spec.add_development_dependency 'bundler-audit', '~> 0.7'
Binary file
Binary file
data/lib/emasser/cli.rb CHANGED
@@ -20,8 +20,8 @@ module Emasser
20
20
  puts "emasser version: #{Emasser::VERSION}".green
21
21
  exit
22
22
  elsif ARGV[0].to_s.include? 'hello'
23
- user_name = ENV['USERNAME'] || 'rookie'
24
- puts "Hello #{user_name} - enjoy using emasser!".cyan
23
+ user_name = ENV.fetch('USERNAME', 'rookie')
24
+ puts "Hello #{user_name} - enjoy using emasser version #{Emasser::VERSION}!".cyan
25
25
  exit
26
26
  end
27
27
 
@@ -33,6 +33,7 @@ module Emasser
33
33
  config.api_key['user-uid'] = raise_unless_present('EMASSER_API_KEY_USER_UID')
34
34
  config.scheme = 'https'
35
35
  config.base_path = '/'
36
+ config.server_index = nil
36
37
  config.host = raise_unless_present('EMASSER_HOST')
37
38
  config.key_file = raise_unless_present('EMASSER_KEY_FILE_PATH')
38
39
  config.cert_file = raise_unless_present('EMASSER_CERT_FILE_PATH')
@@ -5,14 +5,22 @@ module Emasser
5
5
  include_package: false,
6
6
  include_ditpr_metrics: false,
7
7
  include_decommissioned: false,
8
- return_type: 'SystemResponse' # This is used by swagger client only to format output
8
+ debug_return_type: 'SystemResponse' # This is used by swagger client only to format output
9
9
  }.freeze
10
10
 
11
11
  GET_SYSTEM_RETURN_TYPE = {
12
- return_type: 'SystemResponse'
12
+ debug_return_type: 'SystemResponse'
13
13
  }.freeze
14
14
 
15
15
  GET_ARTIFACTS_RETURN_TYPE = {
16
- return_type: 'String'
16
+ debug_return_type: 'String'
17
+ }.freeze
18
+
19
+ GET_WORKFLOWINSTANCES_RETURN_TYPE = {
20
+ debug_return_type: 'Object'
21
+ }.freeze
22
+
23
+ DEL_MILESTONES_RETURN_TYPE = {
24
+ debug_return_type: 'Object'
17
25
  }.freeze
18
26
  end
@@ -55,11 +55,11 @@ module Emasser
55
55
  option :poamId, type: :numeric, required: true, desc: 'A numeric value representing the poam identification'
56
56
 
57
57
  def remove
58
- body = EmassClient::DeletePoam.new
58
+ body = EmassClient::PoamGet.new
59
59
  body.poam_id = options[:poamId]
60
60
  body_array = Array.new(1, body)
61
61
 
62
- result = EmassClient::POAMApi.new.delete_poam(body_array, options[:systemId])
62
+ result = EmassClient::POAMApi.new.delete_poam(options[:systemId], body_array)
63
63
  puts to_output_hash(result).green
64
64
  rescue EmassClient::ApiError => e
65
65
  puts 'Exception when calling POAMApi->delete_poam'.red
@@ -88,16 +88,18 @@ module Emasser
88
88
  desc: 'A numeric value representing the milestone identification'
89
89
 
90
90
  def remove
91
- body = EmassClient::DeleteMilestone.new
91
+ body = EmassClient::MilestonesGet.new
92
92
  body.milestone_id = options[:milestoneId]
93
93
  body_array = Array.new(1, body)
94
94
 
95
- result = EmassClient::MilestonesApi.new.delete_milestone(body_array, options[:systemId], options[:poamId])
96
- # The server returns an empty object upon successfully deleting a milestone.
95
+ # Getting an empty return when utilizing the default return type - using 'Object' as return type
96
+ opts = Emasser::DEL_MILESTONES_RETURN_TYPE
97
+
98
+ result = EmassClient::MilestonesApi.new.delete_milestone(options[:systemId], options[:poamId], body_array, opts)
97
99
  puts to_output_hash(result).green
98
100
  rescue EmassClient::ApiError => e
99
101
  puts 'Exception when calling MilestonesApi->delete_milestone'.red
100
- puts to_output_hash(e)
102
+ puts to_output_hash(e).yellow
101
103
  end
102
104
  end
103
105
 
@@ -125,7 +127,7 @@ module Emasser
125
127
  body_array << obj
126
128
  end
127
129
 
128
- result = EmassClient::ArtifactsApi.new.delete_artifact(body_array, options[:systemId])
130
+ result = EmassClient::ArtifactsApi.new.delete_artifact(options[:systemId], body_array)
129
131
  puts to_output_hash(result).green
130
132
  rescue EmassClient::ApiError => e
131
133
  puts 'Exception when calling ArtifactsApi->delete_artifact'.red
data/lib/emasser/get.rb CHANGED
@@ -58,9 +58,8 @@ module Emasser
58
58
  true
59
59
  end
60
60
 
61
- desc 'id [--system-name [SYSTEM_NAME]] [--system-owner [SYSTEM_OWNER]]',
61
+ desc 'id [--system_name [SYSTEM_NAME]] [--system_owner [SYSTEM_OWNER]]',
62
62
  'Attempts to provide system ID of a system with name [NAME] and owner [SYSTEM_OWNER]'
63
- # desc 'id', 'Get a system ID given "name" or "owner"'
64
63
 
65
64
  # Required parameters/fields
66
65
  option :system_name
@@ -73,26 +72,29 @@ module Emasser
73
72
  end
74
73
 
75
74
  begin
76
- results = EmassClient::SystemsApi.new.get_systems.data
75
+ results = EmassClient::SystemsApi.new.get_systems
77
76
  results = filter_systems(results, options[:system_name], options[:system_owner])
78
77
  results.each { |result| puts "#{result[:systemId]} - #{result[:systemOwner]} - #{result[:name]}" }
79
78
  rescue EmassClient::ApiError => e
80
79
  puts 'Exception when calling SystemsApi->get_systems'
81
- puts to_output_hash(e)
80
+ puts to_output_hash(e).yellow
82
81
  end
83
82
  end
84
83
 
84
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
85
85
  no_commands do
86
86
  def filter_systems(results, system_name = nil, system_owner = nil)
87
+ results = results.to_body if results.respond_to?(:to_body)
87
88
  if system_owner.nil?
88
- results.filter { |result| result[:name].eql?(system_name) }
89
+ results[:data].filter { |result| result[:name].eql?(system_name) }
89
90
  elsif system_name.nil?
90
- results.filter { |result| result[:systemOwner].eql?(system_owner) }
91
+ results[:data].filter { |result| result[:systemOwner].eql?(system_owner) }
91
92
  else
92
- results.filter { |result| result[:name].eql?(system_name) && result[:systemOwner].eql?(system_owner) }
93
+ results[:data].filter { |result| result[:name].eql?(system_name) && result[:systemOwner].eql?(system_owner) }
93
94
  end
94
95
  end
95
96
  end
97
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
96
98
 
97
99
  desc "byId \[options\]", 'Retrieve a system - filtered by [options] params'
98
100
  option :systemId, type: :numeric, required: true,
@@ -110,8 +112,8 @@ module Emasser
110
112
  result = EmassClient::SystemsApi.new.get_system(options[:systemId], optional_options)
111
113
  puts to_output_hash(result).green
112
114
  rescue EmassClient::ApiError => e
113
- puts 'Exception when calling SystemsApi->get_systems'.red
114
- puts to_output_hash(e)
115
+ puts 'Exception when calling SystemsApi->get_system'.red
116
+ puts to_output_hash(e).yellow
115
117
  end
116
118
  end
117
119
  end
@@ -148,7 +150,7 @@ module Emasser
148
150
  puts to_output_hash(result).green
149
151
  rescue EmassClient::ApiError => e
150
152
  puts 'Exception when calling SystemsApi->get_systems'.red
151
- puts to_output_hash(e)
153
+ puts to_output_hash(e).yellow
152
154
  end
153
155
  end
154
156
  end
@@ -174,7 +176,7 @@ module Emasser
174
176
  puts to_output_hash(result).green
175
177
  rescue EmassClient::ApiError => e
176
178
  puts 'Exception when calling SystemRolesApi->get_system_roles'.red
177
- puts to_output_hash(e)
179
+ puts to_output_hash(e).yellow
178
180
  end
179
181
 
180
182
  desc "byCategory \[options\]", 'Retrieves role(s) - filtered by [options] params'
@@ -184,7 +186,7 @@ module Emasser
184
186
  enum: ['AO', 'Auditor', 'Artifact Manager', 'C&A Team', 'IAO',
185
187
  'ISSO', 'PM/IAM', 'SCA', 'User Rep', 'Validator']
186
188
  # Optional parameters/fields
187
- option :policy, type: :string, required: false, enum: %w[diacap rmf reporting]
189
+ option :policy, type: :string, required: false, default: 'rmf', enum: %w[diacap rmf reporting]
188
190
  option :includeDecommissioned, type: :boolean, required: false, desc: 'BOOLEAN - true or false.'
189
191
 
190
192
  def byCategory
@@ -197,7 +199,7 @@ module Emasser
197
199
  puts to_output_hash(result).green
198
200
  rescue EmassClient::ApiError => e
199
201
  puts 'Exception when calling SystemRolesApi->get_system_by_role_category_id'.red
200
- puts to_output_hash(e)
202
+ puts to_output_hash(e).yellow
201
203
  end
202
204
  end
203
205
  end
@@ -230,7 +232,7 @@ module Emasser
230
232
  puts to_output_hash(result).green
231
233
  rescue EmassClient::ApiError => e
232
234
  puts 'Exception when calling ControlsApi->get_system_controls'.red
233
- puts to_output_hash(e)
235
+ puts to_output_hash(e).yellow
234
236
  end
235
237
  end
236
238
  end
@@ -263,7 +265,7 @@ module Emasser
263
265
  puts to_output_hash(result).green
264
266
  rescue EmassClient::ApiError => e
265
267
  puts 'Exception when calling TestResultsApi->get_system_test_results'.red
266
- puts to_output_hash(e)
268
+ puts to_output_hash(e).yellow
267
269
  end
268
270
  end
269
271
  end
@@ -289,8 +291,8 @@ module Emasser
289
291
  desc: 'The schedule completion start date - Unix time format.'
290
292
  option :scheduledCompletionDateEnd, type: :numeric, required: false,
291
293
  desc: 'The scheduled completion end date - Unix time format.'
292
- option :controlAcronyms, type: :string, required: false, desc: 'The system acronym(s) e.g "AC-1, AC-2"'
293
- option :ccis, type: :string, required: false, desc: 'The system CCIS string numerical value'
294
+ option :controlAcronyms, type: :string, required: false, desc: 'The system acronym(s) e.g "AC-1" or "AC-1, AC-2"'
295
+ option :ccis, type: :string, required: false, desc: 'The system CCIS string numerical value e.g "000123" or "000123,000069"'
294
296
  option :systemOnly, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
295
297
 
296
298
  def forSystem
@@ -302,7 +304,7 @@ module Emasser
302
304
  puts to_output_hash(result).green
303
305
  rescue EmassClient::ApiError => e
304
306
  puts 'Exception when calling POAMApi->get_system_poams'.red
305
- puts to_output_hash(e)
307
+ puts to_output_hash(e).yellow
306
308
  end
307
309
  end
308
310
 
@@ -319,7 +321,7 @@ module Emasser
319
321
  puts to_output_hash(result).green
320
322
  rescue EmassClient::ApiError => e
321
323
  puts 'Exception when calling POAMApi->get_system_poams_by_poam_id'.red
322
- puts to_output_hash(e)
324
+ puts to_output_hash(e).yellow
323
325
  end
324
326
  end
325
327
 
@@ -356,7 +358,7 @@ module Emasser
356
358
  puts to_output_hash(result).green
357
359
  rescue EmassClient::ApiError => e
358
360
  puts 'Exception when calling MilestonesApi->get_system_milestones_by_poam_id'.red
359
- puts to_output_hash(e)
361
+ puts to_output_hash(e).yellow
360
362
  end
361
363
  end
362
364
 
@@ -377,7 +379,7 @@ module Emasser
377
379
  puts to_output_hash(result).green
378
380
  rescue EmassClient::ApiError => e
379
381
  puts 'Exception when calling MilestonesApi->get_system_milestones_by_poam_id_and_milestone_id'.red
380
- puts to_output_hash(e)
382
+ puts to_output_hash(e).yellow
381
383
  end
382
384
  end
383
385
 
@@ -393,7 +395,7 @@ module Emasser
393
395
  true
394
396
  end
395
397
 
396
- desc 'system', 'Get all system artifacts for a system Id'
398
+ desc 'forSystem', 'Get all system artifacts for a system Id'
397
399
  # Required parameters/fields
398
400
  option :systemId, type: :numeric, required: true,
399
401
  desc: 'A numeric value representing the system identification'
@@ -414,7 +416,7 @@ module Emasser
414
416
  puts to_output_hash(result).green
415
417
  rescue EmassClient::ApiError => e
416
418
  puts 'Exception when calling ArtifactsApi->get_system_artifacts'.red
417
- puts to_output_hash(e)
419
+ puts to_output_hash(e).yellow
418
420
  end
419
421
  end
420
422
 
@@ -437,7 +439,7 @@ module Emasser
437
439
  options[:systemId], options[:filename], optional_options
438
440
  )
439
441
  if options[:compress]
440
- p result.green
442
+ pp result
441
443
  else
442
444
  begin
443
445
  puts JSON.pretty_generate(JSON.parse(result)).green
@@ -447,7 +449,7 @@ module Emasser
447
449
  end
448
450
  rescue EmassClient::ApiError => e
449
451
  puts 'Exception when calling ArtifactsApi->get_system_artifacts_export'.red
450
- puts to_output_hash(e)
452
+ puts to_output_hash(e).yellow
451
453
  end
452
454
  end
453
455
 
@@ -483,7 +485,7 @@ module Emasser
483
485
  puts to_output_hash(result).green
484
486
  rescue EmassClient::ApiError => e
485
487
  puts 'Exception when calling ApprovalChainApi->get_system_cac'.red
486
- puts to_output_hash(e)
488
+ puts to_output_hash(e).yellow
487
489
  end
488
490
  end
489
491
  end
@@ -514,7 +516,7 @@ module Emasser
514
516
  puts to_output_hash(result).green
515
517
  rescue EmassClient::ApiError => e
516
518
  puts 'Exception when calling ApprovalChainApi->get_system_'.red
517
- puts to_output_hash(e)
519
+ puts to_output_hash(e).yellow
518
520
  end
519
521
  end
520
522
 
@@ -539,7 +541,7 @@ module Emasser
539
541
  puts to_output_hash(result).green
540
542
  rescue EmassClient::ApiError => e
541
543
  puts 'Exception when calling ApprovalChainApi->get_cmmc_assessments'.red
542
- puts to_output_hash(e)
544
+ puts to_output_hash(e).yellow
543
545
  end
544
546
  end
545
547
 
@@ -569,7 +571,7 @@ module Emasser
569
571
  puts to_output_hash(result).green
570
572
  rescue EmassClient::ApiError => e
571
573
  puts 'Exception when calling ApprovalChainApi->get_workflow_definitions'.red
572
- puts to_output_hash(e)
574
+ puts to_output_hash(e).yellow
573
575
  end
574
576
  end
575
577
 
@@ -577,17 +579,14 @@ module Emasser
577
579
  # active and historical workflows for a system.
578
580
  #
579
581
  # Endpoints:
580
- # /api/systems/{systemId}/workflow-instances - Get workflow instances in a system
581
- # /api/systems/{systemId}/workflow-instances/{workflowInstanceId} - Get workflow instance by ID in a system
582
+ # /api/workflows/instances - Get workflow instances in a site
583
+ # /api/workflows/instances/{workflowInstanceId} - Get workflow instance by ID
582
584
  class WorkflowInstances < SubCommandBase
583
585
  def self.exit_on_failure?
584
586
  true
585
587
  end
586
588
 
587
- desc 'forSystem', 'Get workflow instances in a system'
588
- # Required parameters/fields
589
- option :systemId, type: :numeric, required: true,
590
- desc: 'A numeric value representing the system identification'
589
+ desc 'all', 'Get workflow instances in a site'
591
590
 
592
591
  # Optional parameters/fields
593
592
  option :includeComments, type: :boolean, required: false, default: false, desc: 'BOOLEAN - true or false.'
@@ -595,36 +594,32 @@ module Emasser
595
594
  option :sinceDate, type: :string, required: false, desc: 'The workflow instance date. Unix date format'
596
595
  option :status, type: :string, required: false, enum: %w[active inactive all]
597
596
 
598
- def forSystem
597
+ def all
599
598
  optional_options_keys = optional_options(@_initializer).keys
600
599
  optional_options = to_input_hash(optional_options_keys, options)
601
600
 
602
- result = EmassClient::WorkflowInstancesApi.new.get_system_workflow_instances(
603
- options[:systemId], optional_options
604
- )
601
+ result = EmassClient::WorkflowInstancesApi.new.get_system_workflow_instances(optional_options)
605
602
  puts to_output_hash(result).green
606
603
  rescue EmassClient::ApiError => e
607
604
  puts 'Exception when calling ApprovalChainApi->get_system_workflow_instances'.red
608
- puts to_output_hash(e)
605
+ puts to_output_hash(e).yellow
609
606
  end
610
607
 
611
608
  # Workflow by workflowInstanceId ---------------------------------------------------------
612
- desc 'byWorkflowInstanceId', 'Get workflow instance by ID in a system'
609
+ desc 'byInstanceId', 'Get workflow instance by ID'
613
610
 
614
611
  # Required parameters/fields
615
- option :systemId, type: :numeric, required: true,
616
- desc: 'A numeric value representing the system identification'
617
612
  option :workflowInstanceId, type: :numeric, required: true,
618
613
  desc: 'A numeric value representing the workflowInstance identification'
619
614
 
620
- def byWorkflowInstanceId
621
- result = EmassClient::WorkflowInstancesApi.new.get_system_workflow_instances_by_workflow_instance_id(
622
- options[:systemId], options[:workflowInstanceId]
623
- )
615
+ def byInstanceId
616
+ opts = Emasser::GET_WORKFLOWINSTANCES_RETURN_TYPE
617
+ result = EmassClient::WorkflowInstancesApi.new
618
+ .get_system_workflow_instances_by_workflow_instance_id(options[:workflowInstanceId], opts)
624
619
  puts to_output_hash(result).green
625
620
  rescue EmassClient::ApiError => e
626
621
  puts 'Exception when calling ApprovalChainApi->get_system_workflow_instances_by_workflow_instance_id'.red
627
- puts to_output_hash(e)
622
+ puts to_output_hash(e).yellow
628
623
  end
629
624
  end
630
625
 
@@ -0,0 +1,62 @@
1
+ Add cloud resource and scan results in the assets module for a system
2
+
3
+ Endpoint request parameters/fields
4
+
5
+ Field Data Type Details
6
+ -------------------------------------------------------------------------------------------------
7
+ systemId Integer [Required] Unique eMASS identifier. Will need to provide correct number.
8
+ provider String [Required] Cloud service provider name.
9
+ resourceId String [Required] Unique identifier/resource namespace for policy compliance result.
10
+ resourceName String [Required] Friendly name of Cloud resource.
11
+ resourceType String [Required] Type of Cloud resource.
12
+
13
+ initiatedBy String [Optional] Email of POC.
14
+ cspAccountId String [Optional] System/owner's CSP account ID/number.
15
+ cspRegion String [Optional] CSP region of system.
16
+ isBaseline Boolean [Optional] True/false flag for providing results as baseline.
17
+ If true, all existing compliance results for the resourceId will be replaced by results in the current call.
18
+
19
+ tags Object [Optional] Informational tags associated to results for other metadata
20
+ text String [Optional] Tag metadata information
21
+
22
+ complianceResults Object [Required] Compliance result information
23
+ cspPolicyDefinitionId String [Required] Unique identifier/compliance namespace for CSP/Resource’s
24
+ policy definition/compliance check.
25
+ policyDefinitionTitle String [Required] Friendly policy/compliance check title. Recommend short title
26
+ isCompliant Boolean [Required] Compliance status of the policy for the identified cloud resource.
27
+
28
+ complianceCheckTimestamp Date [Optional] Unix date format
29
+ control String [Optional] Comma separated correlation to Security Control
30
+ (e.g. exact NIST Control acronym).
31
+ assessmentProcedure String [Optional] Comma separated correlation to Assessment Procedure
32
+ (i.e. CCI number for DoD Control Set).
33
+ complianceReason String [Optional] Reason/comments for compliance result
34
+ policyDeploymentName String [Optional] Name of policy deployment
35
+ policyDeploymentVersion String [Optional] Version of policy deployment.
36
+ severity String [Optional] Values include the following: (Low, Medium, High, Critical)
37
+
38
+
39
+ The following Cloud Resource parameters/fields have the following character limitations:
40
+ - Fields that can not exceed 50 characters:
41
+ - Policy Deployment Version (`policyDeploymentVersion`)
42
+ - Fields that can not exceed 100 characters:
43
+ - Assessment Procedure (`assessmentProcedure`)
44
+ - Security Control Acronym (`control`)
45
+ - CSP Account ID (`cspAccountId`)
46
+ - CSP Region (`cspRegion`)
47
+ - Email of POC (`initiatedBy`)
48
+ - Cloud Service Provider (`provider`)
49
+ - Type of Cloud resource (`resourceType`)
50
+ - Fields that can not exceed 500 characters:
51
+ - CSP/Resource’s Policy ID (`cspPolicyDefinitionId`)
52
+ - Policy Deployment Name (`policyDeploymentName`)
53
+ - Policy Compliance ID (`resourceId`)
54
+ - Cloud Resource Name (`resourceName`)
55
+ - Fields that can not exceed 1000 characters:
56
+ - Reason for Compliance (`complianceReason`)
57
+ - Fields that can not exceed 2000 characters:
58
+ - Policy Short Title (`policyDefinitionTitle`)
59
+
60
+ Example:
61
+
62
+ bundle exec exe/emasser post cloud_resource add --systemId [value] --provider [value] --resourceId [value] --resourceName [value] --resourceType [value] --cspPolicyDefinitionId [value] --isCompliant or --is-not-Compliant --policyDefinitionTitle [value] --test [value]
@@ -0,0 +1,44 @@
1
+ Add cloud resource and scan results in the assets module for a system
2
+
3
+ Endpoint request parameters/fields
4
+
5
+ Field Data Type Details
6
+ -------------------------------------------------------------------------------------------------
7
+ systemId Integer [Required] Unique eMASS identifier. Will need to provide correct number.
8
+ containerId String [Required] Unique identifier of the container.
9
+ containerName String [Required] Friendly name of the container.
10
+ time Date [Required] Datetime of scan/result. Unix date format.
11
+
12
+ podName String [Optional] Name of pod (e.g. Kubernetes pod).
13
+ podIp String [Optional] IP address of pod.
14
+ namespace String [Optional] Namespace of container in container orchestration (e.g. Kubernetes namespace).
15
+
16
+ tags Object [Optional] Informational tags associated to results for other metadata.
17
+ text String [Optional] Tag metadata information.
18
+
19
+ benchmarks Object
20
+ benchmark String [Required] Identifier of the benchmark/grouping of compliance results.
21
+ (e.g. for STIG results, provide the benchmark id for the STIG technology).
22
+ isBaseline Boolean [Optional] True/false flag for providing results as baseline. If true, all existing
23
+ compliance results for the provided benchmark within the container will be replaced
24
+ by results in the current call.
25
+ results Object
26
+ ruleId String [Required] Identifier for the compliance result, vulnerability, etc.
27
+ status String [Required] Benchmark result status
28
+ lastSeen Date [Required] Date last seen, Unix date format
29
+ message String [Optional] Comments for the result
30
+
31
+ The following Container parameters/fields have the following character limitations:
32
+ - Fields that can not exceed 100 characters:
33
+ - STIG Benchmark ID (`benchmark`)
34
+ - Container Namespace (`namespace`)
35
+ - Kubernetes assigned IP (`podIp`)
36
+ - Kubernetes Pod Name) (`podName`)
37
+ - Fields that can not exceed 500 characters:
38
+ - Container ID (`containerId`)
39
+ - Friendly Container Name (`containerName`)
40
+ - Fields that can not exceed 1000 characters:
41
+ - Result Comments (`message`)
42
+
43
+ Example:
44
+ bundle exec ruby exe/emasser post container add --systemId [value] --containerId [value] --containerName [value] --time [value] --benchmark [value] --lastSeen [value] --ruleId [value] --status [value]
@@ -1,14 +1,111 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OutputConverters
4
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Style/TernaryParentheses
5
+ # rubocop:disable Style/IfWithBooleanLiteralBranches, Style/RescueStandardError, Metrics/BlockNesting
4
6
  def to_output_hash(obj)
7
+ diplay_nulls = (ENV.fetch('EMASSER_CLI_DISPLAY_NULL', 'true').eql? 'true') ? true : false
8
+ diplay_datetime = (ENV.fetch('EMASSER_EPOCH_TO_DATETIME', 'false').eql? 'true') ? true : false
9
+
5
10
  if obj.to_s.include? 'Error message'
6
- obj
11
+ begin
12
+ index = obj.to_s.index('Response body')+14
13
+ arr_obj = obj.to_s[index, obj.to_s.size - index]
14
+ JSON.pretty_generate(JSON.parse(arr_obj))
15
+ rescue
16
+ obj
17
+ end
7
18
  else
8
- hash = obj.instance_variables.each_with_object({}) do |var, h|
9
- h[var.to_s.delete('@')] = obj.instance_variable_get(var)
19
+ obj = obj.to_body if obj.respond_to?(:to_body)
20
+ if !diplay_nulls
21
+ clean_obj = {}
22
+ data_obj = {}
23
+ obj.each do |key, value|
24
+ if key.to_s.include?('meta')
25
+ obj_entry = {}
26
+ obj_entry[:meta] = value
27
+ clean_obj.merge!(obj_entry)
28
+ elsif key.to_s.include?('data')
29
+ if value.is_a?(Array)
30
+ hash_array = []
31
+ value.each do |elements|
32
+ hash_array << elements.compact
33
+ end
34
+ data_obj['data'] = hash_array
35
+ else
36
+ data_obj['data'] = value.nil? ? value : value.compact
37
+ end
38
+ elsif key.to_s.include?('pagination')
39
+ pg_obj = {}
40
+ pg_obj[:pagination] = value
41
+ data_obj.merge!(pg_obj)
42
+ end
43
+ clean_obj.merge!(data_obj)
44
+ end
45
+ obj = clean_obj
46
+ end
47
+
48
+ if diplay_datetime
49
+ clean_obj = {}
50
+ data_obj = {}
51
+ obj.each do |key, value|
52
+ if key.to_s.include?('meta')
53
+ obj_entry = {}
54
+ obj_entry[:meta] = value
55
+ clean_obj.merge!(obj_entry)
56
+ elsif key.to_s.include?('data')
57
+ if value.is_a?(Array)
58
+ hash_array = []
59
+ value.each do |element|
60
+ datetime_obj = change_to_datetime(element)
61
+ hash_array << datetime_obj
62
+ end
63
+ data_obj['data'] = hash_array
64
+ else
65
+ data_obj['data'] = change_to_datetime(value)
66
+ end
67
+ elsif key.to_s.include?('pagination')
68
+ pg_obj = {}
69
+ pg_obj[:pagination] = value
70
+ data_obj.merge!(pg_obj)
71
+ end
72
+ clean_obj.merge!(data_obj)
73
+ end
74
+ obj = clean_obj
75
+ end
76
+ JSON.pretty_generate(obj)
77
+ end
78
+ end
79
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Style/TernaryParentheses
80
+ # rubocop:enable Style/IfWithBooleanLiteralBranches, Style/RescueStandardError, Metrics/BlockNesting
81
+
82
+ # rubocop:disable Style/IdenticalConditionalBranches, Performance/RedundantMatch, Performance/RegexpMatch
83
+ def change_to_datetime(obj)
84
+ if obj.nil?
85
+ return obj
86
+ end
87
+
88
+ data_obj = {}
89
+ obj.each do |key, value|
90
+ obj_entry = {}
91
+ if value.is_a?(Array)
92
+ hash_array = []
93
+ value.each do |element|
94
+ hash_array << change_to_datetime(element)
95
+ end
96
+ obj_entry[key] = hash_array
97
+ data_obj.merge!(obj_entry)
98
+ else
99
+ if /\w(date|Date)/.match(key.to_s)
100
+ value = value.nil? ? value : Time.at(value)
101
+ end
102
+ obj_entry[key] = value
103
+ data_obj.merge!(obj_entry)
10
104
  end
11
- JSON.pretty_generate(hash)
12
105
  end
106
+ # rubocop:disable Style/RedundantReturn
107
+ return data_obj
108
+ # rubocop:enable Style/RedundantReturn
13
109
  end
110
+ # rubocop:enable Style/IdenticalConditionalBranches, Performance/RedundantMatch, Performance/RegexpMatch
14
111
  end