octool 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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