octool 0.0.5 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03d4e6cdc68059584e26dd26983e2085aed2bb5593b1bb78d5307bc9938401d7
4
- data.tar.gz: 15f8bf0c448fb1e1091f7e6ab78fbffba50925a2a7799dd66ff939674d135cea
3
+ metadata.gz: 245e14c9cf523957cca7c2826364125a1f11715a080015124c9477b1c99c6707
4
+ data.tar.gz: '0759efbc98a8ce26407649d2c4c458e273d3711c8661fbc94b6bb13e194a9695'
5
5
  SHA512:
6
- metadata.gz: a944191a813ab2ed2d122862466d79e65df9230e64ade9e73b83aefb8fcb98069bfaba0fec0876c539f63b7f229a16311b0721bd81eeb17b49b7564da2995051
7
- data.tar.gz: e3b99bc6618b4192ba99a570bf6dd6a364c52540b73b39d80817a43e7364fdaf730596578756149e60cda5c0e56d3e75f643abdb11838a983f1d8943df9f0712
6
+ metadata.gz: a27114864b9430e4096429a2d26d13d92ed6bc53ebfb9fa00008e1beb04cc8527f0637d336020826172b47109b192a94b9adfb6eef3036ce160f150be35b6f5d
7
+ data.tar.gz: 684fca7c472d21356ce73e63d6c079c959108ebd5debfb66b10e35acfdf04a899a50c9d669db938f284963159eaa656b4f3c981e560a17b1e3396ae8a7c99da8
data/bin/octool CHANGED
@@ -21,7 +21,7 @@ class App
21
21
  def self.find_config(args)
22
22
  path = args.first || OCTool::DEFAULT_CONFIG_FILENAME
23
23
  path = File.join(path, OCTool::DEFAULT_CONFIG_FILENAME) if File.directory?(path)
24
- path
24
+ File.expand_path(path)
25
25
  end
26
26
 
27
27
  program_desc 'Open Compliance Tool'
@@ -51,6 +51,23 @@ class App
51
51
  v.default_command :data
52
52
  end
53
53
 
54
+ desc 'export data to CSV'
55
+ arg_name 'path/to/system/config.yaml'
56
+ command :csv do |csv|
57
+ csv.desc 'where to store outputs'
58
+ csv.default_value data_dir
59
+ csv.long_desc 'Default output directory respects env vars TMPDIR, TMP, TEMP'
60
+ csv.arg_name 'path/to/output/dir'
61
+ csv.flag [:d, :dir]
62
+
63
+ csv.action do |global_options, options, args|
64
+ export_dir = options[:dir]
65
+ config_file = find_config(args)
66
+ system = OCTool::Parser.new(config_file).load_system
67
+ system.dump export_dir
68
+ end
69
+ end
70
+
54
71
  desc 'validate data and generate System Security Plan'
55
72
  arg_name 'path/to/system/config.yaml'
56
73
  command :ssp do |s|
@@ -92,12 +109,12 @@ class App
92
109
  # Error logic here
93
110
  # Return false to skip default error handling.
94
111
  if ENV['DEBUG']
95
- STDERR.puts exception.message
96
- STDERR.puts exception.backtrace
112
+ warn exception.message
113
+ warn exception.backtrace
97
114
  pp exception
98
115
  false
99
116
  end
100
- STDERR.puts '[FAIL]'
117
+ warn '[FAIL]'
101
118
  true
102
119
  end
103
120
  end
data/lib/octool/parser.rb CHANGED
@@ -4,6 +4,7 @@ module OCTool
4
4
  # Custom error to show validation errors.
5
5
  class ValidationError < StandardError
6
6
  attr_reader :errors
7
+
7
8
  def initialize(path, errors)
8
9
  @path = path
9
10
  @errors = errors
@@ -40,10 +41,9 @@ module OCTool
40
41
  end
41
42
 
42
43
  def validate_file(path, type)
43
- parser = kwalify_parser(type)
44
- data = parser.parse_file(path)
45
- data['type'] = type
46
- errors = parser.errors
44
+ kwal = kwalifyer(type)
45
+ data = kwal.parse_file(path)
46
+ errors = kwal.errors
47
47
  raise ValidationError.new(path, errors) unless errors.empty?
48
48
 
49
49
  RecursiveOpenStruct.new(data, recurse_over_arrays: true, preserve_original_keys: true)
@@ -51,7 +51,7 @@ module OCTool
51
51
  die e.message
52
52
  end
53
53
 
54
- def kwalify_parser(type)
54
+ def kwalifyer(type)
55
55
  schema_file = File.join(schema_dir, "#{type}.yaml")
56
56
  schema = Kwalify::Yaml.load_file(schema_file)
57
57
  validator = Kwalify::Validator.new(schema)
@@ -65,7 +65,7 @@ module OCTool
65
65
  def schema_version
66
66
  @schema_version ||= Kwalify::Yaml.load_file(@config_file)['schema_version']
67
67
  rescue StandarError
68
- STDERR.puts '[FAIL] Unable to read schema_version'
68
+ warn '[FAIL] Unable to read schema_version'
69
69
  exit(1)
70
70
  end
71
71
 
@@ -76,11 +76,45 @@ module OCTool
76
76
  sys = System.new(config)
77
77
  config['includes'].each do |inc|
78
78
  path = File.join(base_dir, inc['path'])
79
- sys.data << validate_file(path, inc['type'])
79
+ sys.data << include_data(path, inc['type'])
80
80
  end
81
81
  sys
82
82
  end
83
83
 
84
+ def include_data(path, type)
85
+ data = validate_file(path, type)
86
+ data['type'] = type
87
+ method("parsed_#{type}".to_sym).call(data)
88
+ end
89
+
90
+ def parsed_component(component)
91
+ component.attestations.map! do |a|
92
+ # Add a "component_key" field to each attestation.
93
+ a['component_key'] = component.component_key
94
+ a.satisfies.map! do |s|
95
+ # Add "attestation_key" to each control satisfied by this attestation.
96
+ s['attestation_key'] = a.summary
97
+ # Add "component_key" to each control satisfied by this attestation.
98
+ s['component_key'] = component.component_key
99
+ s
100
+ end
101
+ a
102
+ end
103
+ component
104
+ end
105
+
106
+ def parsed_standard(standard)
107
+ # Add 'standard_key' to each control family and to each control.
108
+ standard.families.map! { |f| f['standard_key'] = standard.standard_key; f }
109
+ standard.controls.map! { |c| c['standard_key'] = standard.standard_key; c }
110
+ standard
111
+ end
112
+
113
+ def parsed_certification(cert)
114
+ cert.requires.map! { |r| r['certification_key'] = cert.certification_key; r }
115
+ cert
116
+ end
117
+
84
118
  alias load_system validate_data
85
119
  alias load_file validate_file
86
120
  end
data/lib/octool/ssp.rb CHANGED
@@ -18,13 +18,13 @@ module OCTool
18
18
  Paru::Pandoc.new
19
19
  end
20
20
  rescue UncaughtThrowError
21
- STDERR.puts '[FAIL] octool requires pandoc to generate the SSP. Is pandoc installed?'
21
+ warn '[FAIL] octool requires pandoc to generate the SSP. Is pandoc installed?'
22
22
  exit(1)
23
23
  end
24
24
 
25
25
  def generate
26
26
  unless File.writable?(@output_dir)
27
- STDERR.puts "[FAIL] #{@output_dir} is not writable"
27
+ warn "[FAIL] #{@output_dir} is not writable"
28
28
  exit(1)
29
29
  end
30
30
  render_template
data/lib/octool/system.rb CHANGED
@@ -6,73 +6,78 @@ module OCTool
6
6
  attr_accessor :config
7
7
  attr_accessor :data
8
8
 
9
+ TABLE_NAMES = [
10
+ 'components',
11
+ 'satisfies',
12
+ 'attestations',
13
+ 'standards',
14
+ 'controls',
15
+ 'families',
16
+ 'certifications',
17
+ 'requires',
18
+ ].freeze
19
+
9
20
  def initialize(config)
10
21
  @config = config
11
22
  @data = []
12
23
  end
13
24
 
14
25
  def certifications
15
- @certifications ||= @data.select { |e| e.type == 'certification' }
26
+ @certifications ||= data.select { |e| e.type == 'certification' }
16
27
  end
17
28
 
18
29
  def components
19
- @components ||= @data.select { |e| e.type == 'component' }
30
+ @components ||= data.select { |e| e.type == 'component' }
20
31
  end
21
32
 
22
33
  def standards
23
- @standards ||= @data.select { |e| e.type == 'standard' }
34
+ @standards ||= data.select { |e| e.type == 'standard' }
24
35
  end
25
36
 
26
37
  # List of all attestations claimed by components in the system.
27
38
  def attestations
28
- @attestations ||= begin
29
- @attestations = []
30
- components.each do |c|
31
- # Add a "component_key" field to each attestation.
32
- c.attestations.map! { |e| e['component_key'] = c.component_key; e }
33
- @attestations << c.attestations
34
- end
35
- @attestations.flatten!
36
- end
39
+ @attestations ||= components.map(&:attestations).flatten
37
40
  end
38
41
 
39
42
  # List of all coverages.
40
43
  def satisfies
41
- @satisfies ||= begin
42
- @satisfies = []
43
- attestations.each do |a|
44
- # Add an "attestation_key" field to each cover.
45
- a.satisfies.map! { |e| e['component_key'] = a.commponent_key; e }
46
- a.satisfies.map! { |e| e['attestation_key'] = a.attestation_summary; e }
47
- @satisfies << a.satisfies
48
- end
49
- @satisfies.flatten!
50
- end
44
+ @satisfies ||= attestations.map(&:satisfies).flatten
51
45
  end
52
46
 
53
47
  # List of all controls defined by standards in the system.
54
48
  def controls
55
- @controls || begin
56
- @controls = []
57
- standards.each do |s|
58
- # Add a "standard_key" field to each control.
59
- s.controls.map! { |e| e['standard_key'] = s.standard_key; e }
60
- @controls << s.controls
61
- end
62
- @controls.flatten!
63
- end
49
+ @controls ||= standards.map(&:controls).flatten
64
50
  end
65
51
 
66
52
  # List of all families defined by standards in the system.
67
53
  def families
68
- @families || begin
69
- @families = []
70
- standards.each do |s|
71
- # Add a "standard_key" field to each family.
72
- s.families.map! { |e| e['standard_key'] = s.standard_key; e }
73
- @families << s.families
74
- end
75
- @families.flatten!
54
+ @families ||= standards.map(&:families).flatten
55
+ end
56
+
57
+ # List of required controls for all certifications.
58
+ def requires
59
+ @requires ||= certifications.map(&:requires).flatten
60
+ end
61
+
62
+ def dump(writable_dir)
63
+ TABLE_NAMES.each do |type|
64
+ write_csv method(type.to_sym).call, File.join(writable_dir, "#{type}.csv")
65
+ end
66
+ end
67
+
68
+ # Convert array of hashes into a CSV.
69
+ def write_csv(ary, filename)
70
+ ary = ary.map do |e|
71
+ # Convert each element from RecursiveOStruct to a Hash.
72
+ e = e.is_a?(Hash) ? e : e.to_h
73
+ # Throw away nested hashes.
74
+ e.reject { |_, val| val.is_a?(Enumerable) }
75
+ end
76
+ warn "[INFO] write #{filename}"
77
+ CSV.open(filename, 'wb') do |csv|
78
+ column_names = ary.first.keys
79
+ csv << column_names
80
+ ary.each { |hash| csv << hash.values_at(*column_names) }
76
81
  end
77
82
  end
78
83
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OCTool
4
- VERSION = '0.0.5'
4
+ VERSION = '0.0.6'
5
5
  end
data/lib/octool.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'octool/version.rb'
4
4
 
5
5
  # Built-ins.
6
+ require 'csv'
6
7
  require 'pp'
7
8
 
8
9
  # 3rd-party libs.
data/octool.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  == octool - Open Compliance Tool
2
2
 
3
- v0.0.5
3
+ v0.0.6
4
4
 
5
5
  === Global Options
6
6
  === --help
@@ -14,6 +14,18 @@ Display the program version
14
14
 
15
15
 
16
16
  === Commands
17
+ ==== Command: <tt>csv path/to/system/config.yaml</tt>
18
+ export data to CSV
19
+
20
+
21
+ ===== Options
22
+ ===== -d|--dir path/to/output/dir
23
+
24
+ where to store outputs
25
+
26
+ [Default Value] /tmp
27
+ Default output directory respects env vars TMPDIR, TMP, TEMP
28
+
17
29
  ==== Command: <tt>help command</tt>
18
30
  Shows a list of commands or help for one command
19
31
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Morgan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-18 00:00:00.000000000 Z
11
+ date: 2020-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake