octool 0.0.4 → 0.0.5

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: 6a99d4ae79b106f19c3a49be0fd5fa84de52aaf790494a0f78e55c16fd00bbc5
4
- data.tar.gz: d50899b6e334df9a7f40071f053824af296c842e7d11c8add1ae8e0b17c8313b
3
+ metadata.gz: 03d4e6cdc68059584e26dd26983e2085aed2bb5593b1bb78d5307bc9938401d7
4
+ data.tar.gz: 15f8bf0c448fb1e1091f7e6ab78fbffba50925a2a7799dd66ff939674d135cea
5
5
  SHA512:
6
- metadata.gz: d447539ed45f3c6d55eaabdc04763b21a15bcfb1c9a25bcc8db050c885dba0d030634693353614243e59cec9c9622f09289c35d71aec52fdc56a1fc2922e896e
7
- data.tar.gz: 728c1d363e0f30c4c3f52149088d867cefdb0b63e3b3594fbe5aa1e70b04e66749fe2466ed90643fd84e94b416367f59f26e9d4f049741f8b0bb2d61b15f6306
6
+ metadata.gz: a944191a813ab2ed2d122862466d79e65df9230e64ade9e73b83aefb8fcb98069bfaba0fec0876c539f63b7f229a16311b0721bd81eeb17b49b7564da2995051
7
+ data.tar.gz: e3b99bc6618b4192ba99a570bf6dd6a364c52540b73b39d80817a43e7364fdaf730596578756149e60cda5c0e56d3e75f643abdb11838a983f1d8943df9f0712
data/bin/octool CHANGED
@@ -51,7 +51,7 @@ class App
51
51
  v.default_command :data
52
52
  end
53
53
 
54
- desc 'generate System Security Plan'
54
+ desc 'validate data and generate System Security Plan'
55
55
  arg_name 'path/to/system/config.yaml'
56
56
  command :ssp do |s|
57
57
  s.desc 'where to store outputs'
data/lib/octool.rb CHANGED
@@ -8,6 +8,7 @@ require 'pp'
8
8
  # 3rd-party libs.
9
9
  require 'kwalify'
10
10
  require 'kwalify/util/hashlike'
11
+ require 'recursive-open-struct'
11
12
 
12
13
  # OCTool libs.
13
14
  require 'octool/constants'
@@ -15,12 +16,6 @@ require 'octool/parser'
15
16
  require 'octool/ssp'
16
17
  require 'octool/system'
17
18
 
18
- # Generated libs.
19
- require 'octool/generated/certification'
20
- require 'octool/generated/component'
21
- require 'octool/generated/config'
22
- require 'octool/generated/standard'
23
-
24
19
  # Mixins.
25
20
  module OCTool
26
21
  include Kwalify::Util::HashLike # defines [], []=, and keys?
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OCTool
4
- LATEST_SCHEMA_VERSION = 'v1.0.0'
4
+ LATEST_SCHEMA_VERSION = 'v1.0.1'
5
5
  BASE_SCHEMA_DIR = File.join(File.dirname(__FILE__), '..', '..', 'schemas').freeze
6
6
  ERB_DIR = File.join(File.dirname(__FILE__), '..', '..', 'templates').freeze
7
7
  DEFAULT_CONFIG_FILENAME = 'config.yaml'
data/lib/octool/parser.rb CHANGED
@@ -42,10 +42,11 @@ module OCTool
42
42
  def validate_file(path, type)
43
43
  parser = kwalify_parser(type)
44
44
  data = parser.parse_file(path)
45
+ data['type'] = type
45
46
  errors = parser.errors
46
47
  raise ValidationError.new(path, errors) unless errors.empty?
47
48
 
48
- data
49
+ RecursiveOpenStruct.new(data, recurse_over_arrays: true, preserve_original_keys: true)
49
50
  rescue SystemCallError, Kwalify::SyntaxError, ValidationError => e
50
51
  die e.message
51
52
  end
@@ -68,36 +69,19 @@ module OCTool
68
69
  exit(1)
69
70
  end
70
71
 
71
- # Check that all data files are valid.
72
+ # Validate and load data in one pass.
72
73
  def validate_data
73
74
  base_dir = File.dirname(@config_file)
74
75
  config = validate_file(@config_file, 'config')
76
+ sys = System.new(config)
75
77
  config['includes'].each do |inc|
76
78
  path = File.join(base_dir, inc['path'])
77
- type = inc['type']
78
- validate_file(path, type)
79
+ sys.data << validate_file(path, inc['type'])
79
80
  end
80
- config
81
+ sys
81
82
  end
82
83
 
83
- def load_system
84
- base_dir = File.dirname(@config_file)
85
- config = load_file(@config_file, 'config')
86
- system = System.new(config)
87
- config.includes.each do |inc|
88
- path = File.join(base_dir, inc.path)
89
- system.data << load_file(path, inc.type)
90
- end
91
- system
92
- end
93
-
94
- def load_file(path, type)
95
- die "#{File.expand_path(path)} not readable" unless File.readable?(path)
96
- klass = Object.const_get("OCTool::#{type.capitalize}")
97
- ydoc = Kwalify::Yaml.load_file(path)
98
- klass.new(ydoc)
99
- rescue SystemCallError, Kwalify::SyntaxError => e
100
- die e.message
101
- end
84
+ alias load_system validate_data
85
+ alias load_file validate_file
102
86
  end
103
87
  end
data/lib/octool/ssp.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erb'
2
4
 
3
5
  module OCTool
@@ -15,13 +17,13 @@ module OCTool
15
17
  require 'paru/pandoc'
16
18
  Paru::Pandoc.new
17
19
  end
18
- rescue UncaughtThrowError => e
20
+ rescue UncaughtThrowError
19
21
  STDERR.puts '[FAIL] octool requires pandoc to generate the SSP. Is pandoc installed?'
20
22
  exit(1)
21
23
  end
22
24
 
23
25
  def generate
24
- if not File.writable?(@output_dir)
26
+ unless File.writable?(@output_dir)
25
27
  STDERR.puts "[FAIL] #{@output_dir} is not writable"
26
28
  exit(1)
27
29
  end
@@ -39,6 +41,7 @@ module OCTool
39
41
  puts 'done'
40
42
  end
41
43
 
44
+ # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
42
45
  def write(type = 'pdf')
43
46
  out_path = File.join(@output_dir, "ssp.#{type}")
44
47
  print "Building #{out_path} ... "
@@ -55,6 +58,7 @@ module OCTool
55
58
  File.new(out_path, 'wb').write(output)
56
59
  puts 'done'
57
60
  end
61
+ # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
58
62
 
59
63
  def md_path
60
64
  @md_path ||= File.join(@output_dir, 'ssp.md')
data/lib/octool/system.rb CHANGED
@@ -12,15 +12,15 @@ module OCTool
12
12
  end
13
13
 
14
14
  def certifications
15
- @certifications ||= @data.select { |e| e.is_a?(OCTool::Certification) }
15
+ @certifications ||= @data.select { |e| e.type == 'certification' }
16
16
  end
17
17
 
18
18
  def components
19
- @components ||= @data.select { |e| e.is_a?(OCTool::Component) }
19
+ @components ||= @data.select { |e| e.type == 'component' }
20
20
  end
21
21
 
22
22
  def standards
23
- @standards ||= @data.select { |e| e.is_a?(OCTool::Standard) }
23
+ @standards ||= @data.select { |e| e.type == 'standard' }
24
24
  end
25
25
 
26
26
  # List of all attestations claimed by components in the system.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OCTool
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.5'
5
5
  end
data/octool.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  == octool - Open Compliance Tool
2
2
 
3
- v0.0.4
3
+ v0.0.5
4
4
 
5
5
  === Global Options
6
6
  === --help
@@ -25,7 +25,7 @@ List commands one per line, to assist with shell completion
25
25
 
26
26
 
27
27
  ==== Command: <tt>ssp path/to/system/config.yaml</tt>
28
- generate System Security Plan
28
+ validate data and generate System Security Plan
29
29
 
30
30
 
31
31
  ===== Options
@@ -0,0 +1,27 @@
1
+ ---
2
+ type: map
3
+ class: Certification
4
+ mapping:
5
+ certification_key:
6
+ desc: A short, unique identifier for this certification.
7
+ required: true
8
+ type: str
9
+ unique: true
10
+ name:
11
+ desc: A human-friendly name for the certification.
12
+ required: true
13
+ type: str
14
+ requires:
15
+ desc: List of control IDs required by the certification.
16
+ required: true
17
+ type: seq
18
+ sequence:
19
+ - type: map
20
+ class: ControlID
21
+ mapping:
22
+ standard_key:
23
+ required: true
24
+ type: str
25
+ control_key:
26
+ required: true
27
+ type: str
@@ -0,0 +1,60 @@
1
+ ---
2
+ type: map
3
+ class: Component
4
+ mapping:
5
+ name:
6
+ desc: Human-friendly name to appear in the SSP.
7
+ type: str
8
+ required: true
9
+ component_key:
10
+ desc: Unique identifier for referential integrity.
11
+ type: str
12
+ required: true
13
+ description:
14
+ desc: A paragraph or two that describes the component.
15
+ type: str
16
+ required: true
17
+ attestations:
18
+ desc: List of attestations.
19
+ type: seq
20
+ sequence:
21
+ - type: map
22
+ class: Attestation
23
+ mapping:
24
+ summary:
25
+ desc: Arbitrary verbiage to appear in SSP as a TLDR.
26
+ type: str
27
+ required: true
28
+ status:
29
+ desc: To what extent is this attestation "done"?
30
+ type: str
31
+ required: true
32
+ enum:
33
+ - partial
34
+ - complete
35
+ - planned
36
+ - none
37
+ date_verified:
38
+ desc: When was this last verified?
39
+ type: date
40
+ required: false
41
+ satisfies:
42
+ desc: List of control IDs covered by this attestation.
43
+ type: seq
44
+ required: false
45
+ sequence:
46
+ - type: map
47
+ class: ControlID
48
+ mapping:
49
+ standard_key:
50
+ type: text
51
+ required: true
52
+ control_key:
53
+ type: text
54
+ required: true
55
+ narrative:
56
+ desc: |
57
+ Explain how attestation satisfies the indicated controls.
58
+ The content should be in markdown format.
59
+ type: str
60
+ required: true
@@ -0,0 +1,79 @@
1
+ ---
2
+ type: map
3
+ class: Config
4
+ mapping:
5
+ schema_version:
6
+ desc: |
7
+ Must match one of the schema directories in the octool source.
8
+ required: true
9
+ type: str
10
+
11
+ logo:
12
+ desc: Image for title page.
13
+ required: false
14
+ type: map
15
+ class: Logo
16
+ mapping:
17
+ path:
18
+ desc: Path to image.
19
+ type: str
20
+ required: true
21
+ width:
22
+ desc: Width of image, such as "1in" or "254mm"
23
+ type: str
24
+ required: true
25
+
26
+ name:
27
+ desc: Human-friendly to appear in the SSP.
28
+ required: true
29
+ type: str
30
+
31
+ overview:
32
+ desc: Human-friendly description to appear in the SSP.
33
+ required: true
34
+ type: str
35
+
36
+ maintainers:
37
+ desc: Who should somebody contact for questions about this SSP?
38
+ required: true
39
+ type: seq
40
+ sequence:
41
+ - type: str
42
+
43
+ metadata:
44
+ desc: Optional metadata.
45
+ required: false
46
+ type: map
47
+ class: Metadata
48
+ mapping:
49
+ abstract:
50
+ desc: Abstract appears in document metadata.
51
+ required: false
52
+ type: str
53
+ description:
54
+ desc: Description appears in document metadata.
55
+ required: false
56
+ type: str
57
+ '=':
58
+ desc: Arbitrary key:value pair of strings.
59
+ type: str
60
+
61
+ includes:
62
+ desc: Additional files to include from the system repo.
63
+ required: true
64
+ type: seq
65
+ sequence:
66
+ - type: map
67
+ class: Include
68
+ mapping:
69
+ type:
70
+ required: true
71
+ type: str
72
+ enum:
73
+ - certification
74
+ - component
75
+ - standard
76
+ path:
77
+ desc: Path must be relative within the repo.
78
+ required: true
79
+ type: str
@@ -0,0 +1,50 @@
1
+ ---
2
+ type: map
3
+ class: Standard
4
+ mapping:
5
+ name:
6
+ desc: Human-friendly name to appear in SSP.
7
+ type: str
8
+ required: true
9
+
10
+ standard_key:
11
+ desc: Unique ID to use within YAML files.
12
+ type: str
13
+ required: true
14
+
15
+ families:
16
+ desc: Optional list of control families.
17
+ type: seq
18
+ required: false
19
+ sequence:
20
+ - type: map
21
+ class: ControlFamily
22
+ mapping:
23
+ family_key:
24
+ desc: Unique ID of the family
25
+ type: str
26
+ unique: true
27
+ name:
28
+ desc: Human-friendly name of the family
29
+ type: str
30
+ controls:
31
+ desc: Mandatory list of controls defined by the standard.
32
+ required: true
33
+ type: seq
34
+ sequence:
35
+ - type: map
36
+ class: Control
37
+ mapping:
38
+ control_key:
39
+ type: str
40
+ unique: true
41
+ required: true
42
+ family_key:
43
+ type: str
44
+ required: false
45
+ name:
46
+ type: str
47
+ required: true
48
+ description:
49
+ type: str
50
+ required: true
data/templates/ssp.erb CHANGED
@@ -1,5 +1,13 @@
1
1
  ---
2
+ <% if @system.config.logo -%>
3
+ title: |
4
+ ![](<%= @system.config.logo.path -%>){width=<%= @system.config.logo.width %>}
5
+
6
+ <%= @system.config.name %>
7
+ <% else %>
2
8
  title: "<%= @system.config.name -%>"
9
+ <% end %>
10
+
3
11
  subtitle: "System Security Plan"
4
12
 
5
13
  author:
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.4
4
+ version: 0.0.5
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-17 00:00:00.000000000 Z
11
+ date: 2020-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -134,6 +134,20 @@ dependencies:
134
134
  - - '='
135
135
  - !ruby/object:Gem::Version
136
136
  version: 0.4.0.1
137
+ - !ruby/object:Gem::Dependency
138
+ name: recursive-open-struct
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - '='
142
+ - !ruby/object:Gem::Version
143
+ version: 1.1.1
144
+ type: :runtime
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '='
149
+ - !ruby/object:Gem::Version
150
+ version: 1.1.1
137
151
  description:
138
152
  email: jumanjiman@gmail.com
139
153
  executables:
@@ -147,10 +161,6 @@ files:
147
161
  - bin/octool
148
162
  - lib/octool.rb
149
163
  - lib/octool/constants.rb
150
- - lib/octool/generated/certification.rb
151
- - lib/octool/generated/component.rb
152
- - lib/octool/generated/config.rb
153
- - lib/octool/generated/standard.rb
154
164
  - lib/octool/parser.rb
155
165
  - lib/octool/ssp.rb
156
166
  - lib/octool/system.rb
@@ -160,6 +170,10 @@ files:
160
170
  - schemas/v1.0.0/component.yaml
161
171
  - schemas/v1.0.0/config.yaml
162
172
  - schemas/v1.0.0/standard.yaml
173
+ - schemas/v1.0.1/certification.yaml
174
+ - schemas/v1.0.1/component.yaml
175
+ - schemas/v1.0.1/config.yaml
176
+ - schemas/v1.0.1/standard.yaml
163
177
  - templates/ssp.erb
164
178
  homepage: https://github.com/jumanjiman/octool
165
179
  licenses:
@@ -1,35 +0,0 @@
1
- require 'kwalify/util/hashlike'
2
-
3
- module OCTool
4
-
5
-
6
- class Certification
7
- include Kwalify::Util::HashLike
8
- def initialize(hash=nil)
9
- if hash.nil?
10
- return
11
- end
12
- @certification_key = hash['certification_key']
13
- @name = hash['name']
14
- @requires = (v=hash['requires']) ? v.map!{|e| e.is_a?(ControlID) ? e : ControlID.new(e)} : v
15
- end
16
- attr_accessor :certification_key # str
17
- attr_accessor :name # str
18
- attr_accessor :requires # seq
19
- end
20
-
21
-
22
- class ControlID
23
- include Kwalify::Util::HashLike
24
- def initialize(hash=nil)
25
- if hash.nil?
26
- return
27
- end
28
- @standard_key = hash['standard_key']
29
- @control_key = hash['control_key']
30
- end
31
- attr_accessor :standard_key # str
32
- attr_accessor :control_key # str
33
- end
34
-
35
- end
@@ -1,57 +0,0 @@
1
- require 'kwalify/util/hashlike'
2
-
3
- module OCTool
4
-
5
-
6
- class Component
7
- include Kwalify::Util::HashLike
8
- def initialize(hash=nil)
9
- if hash.nil?
10
- return
11
- end
12
- @name = hash['name']
13
- @component_key = hash['component_key']
14
- @description = hash['description']
15
- @attestations = (v=hash['attestations']) ? v.map!{|e| e.is_a?(Attestation) ? e : Attestation.new(e)} : v
16
- end
17
- attr_accessor :name # str
18
- attr_accessor :component_key # str
19
- attr_accessor :description # str
20
- attr_accessor :attestations # seq
21
- end
22
-
23
-
24
- class Attestation
25
- include Kwalify::Util::HashLike
26
- def initialize(hash=nil)
27
- if hash.nil?
28
- return
29
- end
30
- @summary = hash['summary']
31
- @status = hash['status']
32
- @date_verified = hash['date_verified']
33
- @satisfies = (v=hash['satisfies']) ? v.map!{|e| e.is_a?(ControlID) ? e : ControlID.new(e)} : v
34
- @narrative = hash['narrative']
35
- end
36
- attr_accessor :summary # str
37
- attr_accessor :status # str
38
- attr_accessor :date_verified # date
39
- attr_accessor :satisfies # seq
40
- attr_accessor :narrative # str
41
- end
42
-
43
-
44
- class ControlID
45
- include Kwalify::Util::HashLike
46
- def initialize(hash=nil)
47
- if hash.nil?
48
- return
49
- end
50
- @standard_key = hash['standard_key']
51
- @control_key = hash['control_key']
52
- end
53
- attr_accessor :standard_key # text
54
- attr_accessor :control_key # text
55
- end
56
-
57
- end
@@ -1,55 +0,0 @@
1
- require 'kwalify/util/hashlike'
2
-
3
- module OCTool
4
-
5
-
6
- class Config
7
- include Kwalify::Util::HashLike
8
- def initialize(hash=nil)
9
- if hash.nil?
10
- return
11
- end
12
- @schema_version = hash['schema_version']
13
- @name = hash['name']
14
- @overview = hash['overview']
15
- @maintainers = hash['maintainers']
16
- @metadata = (v=hash['metadata']) && v.is_a?(Hash) ? Metadata.new(v) : v
17
- @includes = (v=hash['includes']) ? v.map!{|e| e.is_a?(Include) ? e : Include.new(e)} : v
18
- end
19
- attr_accessor :schema_version # str
20
- attr_accessor :name # str
21
- attr_accessor :overview # str
22
- attr_accessor :maintainers # seq
23
- attr_accessor :metadata # map
24
- attr_accessor :includes # seq
25
- end
26
-
27
- ## Optional metadata.
28
- class Metadata
29
- include Kwalify::Util::HashLike
30
- def initialize(hash=nil)
31
- if hash.nil?
32
- return
33
- end
34
- @abstract = hash['abstract']
35
- @description = hash['description']
36
- end
37
- attr_accessor :abstract # str
38
- attr_accessor :description # str
39
- end
40
-
41
-
42
- class Include
43
- include Kwalify::Util::HashLike
44
- def initialize(hash=nil)
45
- if hash.nil?
46
- return
47
- end
48
- @type = hash['type']
49
- @path = hash['path']
50
- end
51
- attr_accessor :type # str
52
- attr_accessor :path # str
53
- end
54
-
55
- end
@@ -1,55 +0,0 @@
1
- require 'kwalify/util/hashlike'
2
-
3
- module OCTool
4
-
5
-
6
- class Standard
7
- include Kwalify::Util::HashLike
8
- def initialize(hash=nil)
9
- if hash.nil?
10
- return
11
- end
12
- @name = hash['name']
13
- @standard_key = hash['standard_key']
14
- @families = (v=hash['families']) ? v.map!{|e| e.is_a?(ControlFamily) ? e : ControlFamily.new(e)} : v
15
- @controls = (v=hash['controls']) ? v.map!{|e| e.is_a?(Control) ? e : Control.new(e)} : v
16
- end
17
- attr_accessor :name # str
18
- attr_accessor :standard_key # str
19
- attr_accessor :families # seq
20
- attr_accessor :controls # seq
21
- end
22
-
23
-
24
- class ControlFamily
25
- include Kwalify::Util::HashLike
26
- def initialize(hash=nil)
27
- if hash.nil?
28
- return
29
- end
30
- @family_key = hash['family_key']
31
- @name = hash['name']
32
- end
33
- attr_accessor :family_key # str
34
- attr_accessor :name # str
35
- end
36
-
37
-
38
- class Control
39
- include Kwalify::Util::HashLike
40
- def initialize(hash=nil)
41
- if hash.nil?
42
- return
43
- end
44
- @control_key = hash['control_key']
45
- @family_key = hash['family_key']
46
- @name = hash['name']
47
- @description = hash['description']
48
- end
49
- attr_accessor :control_key # str
50
- attr_accessor :family_key # str
51
- attr_accessor :name # str
52
- attr_accessor :description # str
53
- end
54
-
55
- end