octool 0.0.6 → 0.0.11

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: 245e14c9cf523957cca7c2826364125a1f11715a080015124c9477b1c99c6707
4
- data.tar.gz: '0759efbc98a8ce26407649d2c4c458e273d3711c8661fbc94b6bb13e194a9695'
3
+ metadata.gz: 7421bbf076967b16d0210f813f936c0a75b572694071ad6674cdbd2368bfc5ff
4
+ data.tar.gz: 849f56075a2a9815fdb225518fb3579c817ed570382f8cd3a3b2f35916d6e9a4
5
5
  SHA512:
6
- metadata.gz: a27114864b9430e4096429a2d26d13d92ed6bc53ebfb9fa00008e1beb04cc8527f0637d336020826172b47109b192a94b9adfb6eef3036ce160f150be35b6f5d
7
- data.tar.gz: 684fca7c472d21356ce73e63d6c079c959108ebd5debfb66b10e35acfdf04a899a50c9d669db938f284963159eaa656b4f3c981e560a17b1e3396ae8a7c99da8
6
+ metadata.gz: 5bb0a131801cc5003fc2102e7efcab828a6f65099b9f0e65e5df4472ff137ba1f52479b7b9f454cfe75f3551d36d6c6cdfe94cccbf9429aeff2a847713afd779
7
+ data.tar.gz: ee327ac99c2a3036c474ffb7d370c99d23af9afc2e3bc36a6d1fd10573f8f0e7f0e872633797ee25819bafe9f3dd73f0871a4d23741f6ce41f2dc14e69c82bc1
data/bin/octool CHANGED
@@ -77,12 +77,18 @@ class App
77
77
  s.arg_name 'path/to/output/dir'
78
78
  s.flag [:d, :dir]
79
79
 
80
+ s.desc 'Set SSP version'
81
+ s.default_value OCTool::DEFAULT_SSP_VERSION
82
+ s.long_desc 'Underscores are replaced by spaces'
83
+ s.arg_name 'VERSION'
84
+ s.flag :version
85
+
80
86
  s.action do |global_options, options, args|
81
87
  export_dir = options[:dir]
82
88
  config_file = find_config(args)
83
89
  system = OCTool::Parser.new(config_file).load_system
84
90
  Dir.chdir File.dirname(config_file) do
85
- OCTool::SSP.new(system, export_dir).generate
91
+ OCTool::SSP.new(system, export_dir).generate(options[:version])
86
92
  end
87
93
  end
88
94
  end
@@ -4,12 +4,12 @@ require 'octool/version.rb'
4
4
 
5
5
  # Built-ins.
6
6
  require 'csv'
7
+ require 'json'
7
8
  require 'pp'
8
9
 
9
10
  # 3rd-party libs.
10
11
  require 'kwalify'
11
12
  require 'kwalify/util/hashlike'
12
- require 'recursive-open-struct'
13
13
 
14
14
  # OCTool libs.
15
15
  require 'octool/constants'
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OCTool
4
- LATEST_SCHEMA_VERSION = 'v1.0.1'
4
+ LATEST_SCHEMA_VERSION = 'v1.0.2'
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'
8
8
  DEFAULT_OUTPUT_DIR = '/data'
9
+ DEFAULT_SSP_VERSION = 'unset'
9
10
  end
@@ -41,12 +41,12 @@ module OCTool
41
41
  end
42
42
 
43
43
  def validate_file(path, type)
44
- kwal = kwalifyer(type)
45
- data = kwal.parse_file(path)
46
- errors = kwal.errors
44
+ kwalify = kwalifyer(type)
45
+ data = kwalify.parse_file(path)
46
+ errors = kwalify.errors
47
47
  raise ValidationError.new(path, errors) unless errors.empty?
48
48
 
49
- RecursiveOpenStruct.new(data, recurse_over_arrays: true, preserve_original_keys: true)
49
+ data
50
50
  rescue SystemCallError, Kwalify::SyntaxError, ValidationError => e
51
51
  die e.message
52
52
  end
@@ -88,14 +88,14 @@ module OCTool
88
88
  end
89
89
 
90
90
  def parsed_component(component)
91
- component.attestations.map! do |a|
91
+ component['attestations'].map! do |a|
92
92
  # Add a "component_key" field to each attestation.
93
- a['component_key'] = component.component_key
94
- a.satisfies.map! do |s|
93
+ a['component_key'] = component['component_key']
94
+ a['satisfies'].map! do |s|
95
95
  # Add "attestation_key" to each control satisfied by this attestation.
96
- s['attestation_key'] = a.summary
96
+ s['attestation_key'] = a['summary']
97
97
  # Add "component_key" to each control satisfied by this attestation.
98
- s['component_key'] = component.component_key
98
+ s['component_key'] = component['component_key']
99
99
  s
100
100
  end
101
101
  a
@@ -105,13 +105,13 @@ module OCTool
105
105
 
106
106
  def parsed_standard(standard)
107
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 }
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
110
  standard
111
111
  end
112
112
 
113
113
  def parsed_certification(cert)
114
- cert.requires.map! { |r| r['certification_key'] = cert.certification_key; r }
114
+ cert['requires'].map! { |r| r['certification_key'] = cert['certification_key']; r }
115
115
  cert
116
116
  end
117
117
 
@@ -1,13 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'date'
3
4
  require 'erb'
4
5
 
5
6
  module OCTool
6
7
  # Build DB, CSV, and markdown.
7
8
  class SSP
9
+ attr_reader :build_date
10
+ attr_reader :version
11
+
8
12
  def initialize(system, output_dir)
9
13
  @system = system
10
14
  @output_dir = output_dir
15
+ @version = OCTool::DEFAULT_SSP_VERSION
16
+ @build_date = DateTime.now
17
+ end
18
+
19
+ def version=(version)
20
+ # LaTeX fancyheader aborts on underscore in footer.
21
+ @version = version.to_s.gsub(/_+/, ' ')
11
22
  end
12
23
 
13
24
  def pandoc
@@ -22,12 +33,14 @@ module OCTool
22
33
  exit(1)
23
34
  end
24
35
 
25
- def generate
36
+ def generate(version = nil)
37
+ self.version = version if version
26
38
  unless File.writable?(@output_dir)
27
39
  warn "[FAIL] #{@output_dir} is not writable"
28
40
  exit(1)
29
41
  end
30
42
  render_template
43
+ write_acronyms
31
44
  write 'pdf'
32
45
  write 'docx'
33
46
  end
@@ -41,18 +54,30 @@ module OCTool
41
54
  puts 'done'
42
55
  end
43
56
 
57
+ def write_acronyms
58
+ return unless @system.acronyms
59
+
60
+ out_path = File.join(@output_dir, 'acronyms.json')
61
+ File.open(out_path, 'w') { |f| f.write JSON.pretty_generate(@system.acronyms) }
62
+ ENV['PANDOC_ACRONYMS_ACRONYMS'] = out_path
63
+ end
64
+
44
65
  # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
45
66
  def write(type = 'pdf')
46
67
  out_path = File.join(@output_dir, "ssp.#{type}")
47
68
  print "Building #{out_path} ... "
48
69
  converter = pandoc.configure do
49
- from 'markdown'
70
+ from 'markdown+autolink_bare_uris'
50
71
  to type
51
72
  pdf_engine 'lualatex'
52
73
  toc
53
74
  toc_depth 3
54
75
  number_sections
55
76
  highlight_style 'pygments'
77
+ filter 'pandoc-acronyms' if ENV['PANDOC_ACRONYMS_ACRONYMS']
78
+ # https://en.wikibooks.org/wiki/LaTeX/Source_Code_Listings#Encoding_issue
79
+ # Uncomment the following line after the "listings" package is compatible with utf8
80
+ # listings
56
81
  end
57
82
  output = converter << File.read(md_path)
58
83
  File.new(out_path, 'wb').write(output)
@@ -22,57 +22,58 @@ module OCTool
22
22
  @data = []
23
23
  end
24
24
 
25
+ def acronyms
26
+ @acronyms ||= config['acronyms']
27
+ end
28
+
25
29
  def certifications
26
- @certifications ||= data.select { |e| e.type == 'certification' }
30
+ @certifications ||= data.select { |e| e['type'] == 'certification' }
27
31
  end
28
32
 
29
33
  def components
30
- @components ||= data.select { |e| e.type == 'component' }
34
+ @components ||= data.select { |e| e['type'] == 'component' }
31
35
  end
32
36
 
33
37
  def standards
34
- @standards ||= data.select { |e| e.type == 'standard' }
38
+ @standards ||= data.select { |e| e['type'] == 'standard' }
35
39
  end
36
40
 
37
41
  # List of all attestations claimed by components in the system.
38
42
  def attestations
39
- @attestations ||= components.map(&:attestations).flatten
43
+ @attestations ||= components.map { |c| c['attestations'] }.flatten
40
44
  end
41
45
 
42
46
  # List of all coverages.
43
47
  def satisfies
44
- @satisfies ||= attestations.map(&:satisfies).flatten
48
+ @satisfies ||= attestations.map { |a| a['satisfies'] }.flatten
45
49
  end
46
50
 
47
51
  # List of all controls defined by standards in the system.
48
52
  def controls
49
- @controls ||= standards.map(&:controls).flatten
53
+ @controls ||= standards.map { |s| s['controls'] }.flatten
50
54
  end
51
55
 
52
56
  # List of all families defined by standards in the system.
53
57
  def families
54
- @families ||= standards.map(&:families).flatten
58
+ @families ||= standards.map { |s| s['families'] }.flatten
55
59
  end
56
60
 
57
61
  # List of required controls for all certifications.
58
62
  def requires
59
- @requires ||= certifications.map(&:requires).flatten
63
+ @requires ||= certifications.map { |c| c['requires'] }.flatten
60
64
  end
61
65
 
62
66
  def dump(writable_dir)
63
- TABLE_NAMES.each do |type|
64
- write_csv method(type.to_sym).call, File.join(writable_dir, "#{type}.csv")
67
+ TABLE_NAMES.each do |table|
68
+ write_csv method(table.to_sym).call, File.join(writable_dir, "#{table}.csv")
65
69
  end
66
70
  end
67
71
 
68
72
  # Convert array of hashes into a CSV.
69
73
  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
74
+ # Throw away nested hashes. The parser already created separate tables for them.
75
+ ary = ary.map { |e| e.reject { |_, val| val.is_a?(Enumerable) } }
76
+
76
77
  warn "[INFO] write #{filename}"
77
78
  CSV.open(filename, 'wb') do |csv|
78
79
  column_names = ary.first.keys
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OCTool
4
- VERSION = '0.0.6'
4
+ VERSION = '0.0.11'
5
5
  end
@@ -1,6 +1,6 @@
1
1
  == octool - Open Compliance Tool
2
2
 
3
- v0.0.6
3
+ v0.0.11
4
4
 
5
5
  === Global Options
6
6
  === --help
@@ -48,6 +48,13 @@ where to store outputs
48
48
  [Default Value] /tmp
49
49
  Default output directory respects env vars TMPDIR, TMP, TEMP
50
50
 
51
+ ===== --version VERSION
52
+
53
+ Set SSP version
54
+
55
+ [Default Value] unset
56
+ Underscores are replaced by spaces
57
+
51
58
  ==== Command: <tt>validate </tt>
52
59
  Check sanity of configuration
53
60
 
@@ -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,111 @@
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
80
+
81
+ acronyms:
82
+ desc: |
83
+ List of acronyms to be referenced in the doc.
84
+
85
+ The acronyms follow the forms and usage described by the pandoc filter
86
+ https://gitlab.com/mirkoboehm/pandoc-acronyms
87
+
88
+ If your config.yaml includes acronyms, the filter is automatically invoked.
89
+ required: false
90
+ type: map
91
+ mapping:
92
+ '=':
93
+ desc: |
94
+ Acronym as used in the doc source, such as "bba".
95
+ The source usually refers to the acronym with syntax "[!bba]",
96
+ but other syntax forms are possible (see upstream doc).
97
+ type: map
98
+ class: Acronym
99
+ mapping:
100
+ shortform:
101
+ desc: The short form of the expanded acronym, such as "BBA".
102
+ required: true
103
+ type: str
104
+ longform:
105
+ desc: |
106
+ The expanded form of the abbreviation, such as "Beer Brewing Attitude".
107
+ The first instance of "[!bba]" in the doc is automatically expanded to
108
+ "<longform> (<shortform>)".
109
+ Example: "[!bba]" expands to "Beer Brewing Attitude (BBA)".
110
+ required: true
111
+ 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
@@ -1,29 +1,35 @@
1
1
  ---
2
- <% if @system.config.logo -%>
2
+ <% if @system.config['logo'] -%>
3
3
  title: |
4
- ![](<%= @system.config.logo.path -%>){width=<%= @system.config.logo.width %>}
4
+ ![](<%= @system.config['logo']['path'] -%>){width=<%= @system.config['logo']['width'] %>}
5
5
 
6
- <%= @system.config.name %>
6
+ <%= @system.config['name'] %>
7
7
  <% else %>
8
- title: "<%= @system.config.name -%>"
8
+ title: "<%= @system.config['name'] -%>"
9
9
  <% end %>
10
10
 
11
- subtitle: "System Security Plan"
11
+ subtitle: |
12
+ System Security Plan
13
+
14
+ <%=build_date.strftime('%Y-%b-%d')%>
15
+
16
+ <% unless version == OCTool::DEFAULT_SSP_VERSION -%>
17
+ Version <%=version%>
18
+ <% end -%>
12
19
 
13
20
  author:
14
- <% @system.config.maintainers.each do |maintainer| %>
21
+ <% @system.config['maintainers'].each do |maintainer| -%>
15
22
  - <%= maintainer -%>
16
23
  <% end %>
17
24
 
18
25
  absract: |
19
- <%= @system.config.metadata.abstract rescue 'None' %>
26
+ <%= @system.config['metadata']['abstract'] rescue 'None' %>
20
27
 
21
28
  description: |
22
- <%= @system.config.metadata.description rescue 'None' %>
29
+ <%= @system.config['metadata']['description'] rescue 'None' %>
23
30
 
24
31
  fontsize: 11pt
25
32
  mainfont: NotoSans
26
- #monofont: NotoSansMono-ExtraCondensedLight
27
33
  monofont: NotoSansMono-ExtraCondensed
28
34
  mainfontoptions:
29
35
  - Numbers=Lowercase
@@ -49,55 +55,195 @@ pagestyle: headings
49
55
  papersize: letter
50
56
  geometry:
51
57
  - top=2cm
52
- - left=2cm
58
+ - left=3cm
53
59
  - right=2cm
54
60
  - bottom=2cm
61
+
62
+ header-includes:
63
+ - |
64
+ ```{=latex}
65
+ % https://ctan.org/pkg/metalogo?lang=en
66
+ \usepackage{metalogo}
67
+ ```
68
+ - |
69
+ ```{=latex}
70
+ % https://github.com/jgm/pandoc/wiki/Pandoc-Tricks#left-aligning-tables-in-latex
71
+ \usepackage[margins=raggedright]{floatrow}
72
+ ```
73
+ - |
74
+ ```{=latex}
75
+ % https://github.com/jgm/pandoc/wiki/Pandoc-Tricks#definition-list-terms-on-their-own-line-in-latex
76
+ % "Clone" the original \item command
77
+ \let\originalitem\item
78
+
79
+ % Redefine the \item command using the "clone"
80
+ \makeatletter
81
+ \renewcommand{\item}[1][\@nil]{%
82
+ \def\tmp{#1}%
83
+ \ifx\tmp\@nnil\originalitem\else\originalitem[#1]\hfill\par\fi}
84
+ \makeatother
85
+ ```
86
+ - |
87
+ ```{=latex}
88
+ % The are at least two ways to configure how LaTeX floats figures.
89
+ %
90
+ % 1. One approach is described in section 17.2 of
91
+ % http://tug.ctan.org/tex-archive/info/epslatex/english/epslatex.pdf
92
+ % However, the approach described there requires to teach people
93
+ % how to write LaTeX cross-references in markdown.
94
+ %
95
+ % 2. Force figures, listings, etc., to float "[H]ere".
96
+ % This is a LaTeX anti-pattern because it causes large gaps of whitespace on some pages.
97
+ % This approach avoids having to teach people to create LaTeX cross-references.
98
+ % https://tex.stackexchange.com/a/101726
99
+ %
100
+ % Use option 2.
101
+ \usepackage{float}
102
+ \floatplacement{figure}{H}
103
+ ```
104
+ - |
105
+ ```{=latex}
106
+ % https://tex.stackexchange.com/a/32537
107
+ \usepackage{lastpage}
108
+
109
+ % https://ctan.org/pkg/fancyhdr?lang=en
110
+ \usepackage{fancyhdr}
111
+
112
+ \pagestyle{fancy}
113
+ <% unless version == OCTool::DEFAULT_SSP_VERSION %>
114
+ \fancyfoot[L]{Version: <%=version-%>}
115
+ <% end %>
116
+ \fancyfoot[C]{<%=build_date.strftime('%Y-%b-%d')-%>}
117
+ \fancyfoot[R]{\thepage\ of\ \pageref{LastPage}}
118
+ \renewcommand{\footrulewidth}{0.4pt} % thickness
119
+ \renewcommand{\headrulewidth}{0.4pt} % thickness
120
+ \fancypagestyle{plain}{\fancyhead{}\renewcommand{\headrule}{}}
121
+ ```
122
+ - |
123
+ ```{=latex}
124
+ % Which bullet glyphs are avaiable?
125
+ % http://texdoc.net/texmf-dist/doc/latex/comprehensive/symbols-a4.pdf TABLE 50
126
+ %
127
+ % https://learnbyexample.github.io/tutorial/ebook-generation/customizing-pandoc/
128
+ % https://tex.stackexchange.com/questions/174244/change-the-shape-of-the-bullet-list
129
+ % https://texblog.org/2008/10/16/lists-enumerate-itemize-description-and-how-to-change-them/
130
+ % https://tex.stackexchange.com/a/64899
131
+ % https://ctan.org/pkg/enumitem?lang=en
132
+ % https://www.latex4technics.com/?note=2vy0
133
+ %
134
+ %\usepackage{amsfonts}
135
+ %
136
+ % Make bullets small
137
+ %\renewcommand{\labelitemi}{\tiny $\textbullet$}
138
+ %\renewcommand{\labelitemii}{\tiny $\textopenbullet$}
139
+ %\renewcommand{\labelitemiii}{\tiny $\triangleright$}
140
+ %
141
+ % Align bullets to left margin and make small
142
+ % https://tex.stackexchange.com/a/86408
143
+ %\usepackage{enumitem}
144
+ %\usepackage{graphicx}
145
+ %\setlist[itemize,1]{leftmargin=*,label=\scalebox{.8}{$\textbullet$}}
146
+ %\setlist[itemize,2]{leftmargin=*,label=\scalebox{.8}{$\textopenbullet$}}
147
+ %\setlist[itemize,3]{leftmargin=*,label=\scalebox{.8}{\triangleright}}
148
+ %
149
+ % Align bullets to left margin and use normal font
150
+ \usepackage{enumitem}
151
+ \setlist[itemize,1]{leftmargin=*,label=$\textbullet$}
152
+ \setlist[itemize,2]{leftmargin=*,label=$\textopenbullet$}
153
+ \setlist[itemize,3]{leftmargin=*,label=\triangleright}
154
+ %
155
+ % Align bullets to left margin and use slightly smaller font
156
+ %\usepackage{MnSymbol}
157
+ %\setlist[itemize,1]{leftmargin=*,label=$\bullet$}
158
+ %\setlist[itemize,2]{leftmargin=*,label=$\circ$}
159
+ %\setlist[itemize,3]{leftmargin=*,label=\blacktriangleright}
160
+ ```
55
161
  ---
56
162
 
57
- # <%= @system.config.name %>
163
+ # Introduction
58
164
 
59
- ## Overview
165
+ ## About this document
60
166
 
61
- <%= @system.config.overview %>
167
+ A System Security Plan (SSP) is a document to describe security controls in use
168
+ on an information system and their implementation. An SSP provides:
169
+
170
+ - Narrative of security control implementation
171
+ - Description of components and services
172
+ - System data flows and authorization boundaries
173
+
174
+ The SSP is also a tool to guide the assessment of the effectiveness
175
+ of controls within the system.
62
176
 
63
177
  ## Standards
64
178
 
65
- This System Security Plan (SSP) addresses these standards:
179
+ This SSP draws from these standards:
66
180
 
67
181
  <% @system.standards.each do |s| -%>
68
- - <%= s.name %>
182
+ - <%=s['name']-%> (<%=s['standard_key']-%>)
69
183
  <% end %>
70
184
 
71
185
  The full copy of each standard is included in the appendix.
72
186
 
73
187
 
74
- ## Components
188
+ ## Certifications
75
189
 
76
- <% @system.components.each do |c| %>
77
- ### <%= c.name %>
190
+ A certification is a logical grouping of controls that are of interest to
191
+ a given subject. A particular certification does not necessarily target all
192
+ controls from a standard, nor does a particular certification need to draw
193
+ from a single standard.
78
194
 
79
- <%= c.description %>
195
+ This SSP addresses these certifications:
196
+
197
+ <% @system.certifications.each do |c| -%>
198
+ - <%=c['name']%>
199
+
200
+ <% c['requires'].each do |r| -%>
201
+ - <%=r['standard_key']-%> control <%=r['control_key']%>
202
+ <% end -%>
80
203
 
81
- <% if c.attestations.empty? %>
82
- _The organization has not yet documented attestations for this component_.
83
- <% else %>
84
- The organization offers the following attestations for this component.
85
204
  <% end %>
86
205
 
87
- <% c.attestations.each do |a| %>
88
- #### <%= a.summary %>
89
206
 
90
- Status: <%= a.status %>
207
+ # <%= @system.config['name'] %>
91
208
 
92
- Date verified: <%= a.date_verified if a.date_verified %>
209
+ ## Overview
93
210
 
94
- Satisfies:
211
+ <%= @system.config['overview'] %>
95
212
 
96
- <% a.satisfies.each do |cid| -%>
97
- - <%= cid.standard_key %> control <%= cid.control_key %>
98
- <% end -%>
99
213
 
100
- <%= a.narrative %>
214
+ ## Components
215
+
216
+ <% @system.components.each do |c| %>
217
+ ### <%= c['name'] %>
218
+
219
+ <%= c['description'] %>
220
+
221
+ <% if c['attestations'].empty? %>
222
+ _The organization has not yet documented attestations for this component_.
223
+ <% else %>
224
+ The organization offers the following attestations for this component.
225
+ <% end %>
226
+
227
+ <% c['attestations'].compact.each do |a| %>
228
+ #### <%= a['summary'] %>
229
+
230
+ +----------+---------------+--------------------------------------------------------------+
231
+ | Status | Date verified | Satisfies |
232
+ +==========+===============+==============================================================+
233
+ <%
234
+ s = a['satisfies'][0]
235
+ verbiage = sprintf('%-58s', [s['standard_key'], 'control', s['control_key']].join(' '))
236
+ -%>
237
+ | <%=sprintf('%-8s', a['status'])-%> | <%=sprintf('%-13s', a['date_verified'])-%> | - <%=verbiage-%> |
238
+ <%
239
+ a['satisfies'][1..].each do |s|
240
+ verbiage = sprintf('%-58s', [s['standard_key'], 'control', s['control_key']].join(' '))
241
+ -%>
242
+ | | | - <%=verbiage-%> |
243
+ <% end -%>
244
+ +----------+---------------+--------------------------------------------------------------+
245
+
246
+ <%= a['narrative'] %>
101
247
 
102
248
  <% end %>
103
249
  <% end %>
@@ -106,25 +252,60 @@ Satisfies:
106
252
  # Appendix: Standards
107
253
 
108
254
  <% @system.standards.each do |s| %>
109
- ## <%=s.name %>
255
+ ## <%=s['name'] %>
110
256
 
111
- <% if s.families and !s.families.empty? %>
257
+ <% if s['families'] and !s['families'].empty? %>
112
258
  ### Families
113
259
 
114
- <% s.families.each do |family| %>
115
- <%= family.family_key %>
116
- ~ <%= family.name %>
260
+ <%=s['name']-%> categorizes controls into logical groups called families.
117
261
 
118
- <% end %>
262
+ | Family abbreviation | Family name |
263
+ | -------------------------- | -------------------- |
264
+ <% s['families'].each do |family| -%>
265
+ | <%=family['family_key']-%> | <%=family['name']-%> |
266
+ <% end -%>
267
+
268
+ : Control families for <%=s['name']%>
119
269
 
120
270
  <% end %>
121
271
 
122
272
  ### Controls
123
273
 
124
- <% s.controls.each do |c| %>
125
- #### Control <%= c.control_key -%>: <%= c.name %>
274
+ <% s['controls'].each do |c| %>
275
+ #### Control <%= c['control_key'] -%>: <%= c['name'] %>
126
276
 
127
- <%= c.description %>
277
+ <%= c['description'] %>
128
278
 
129
279
  <% end %>
130
280
  <% end %>
281
+
282
+
283
+ # Colophon
284
+
285
+ This document was typeset in NotoSans with \LuaTeX\.
286
+ The main body font is 11-point, and
287
+ code snippets use NotoSansMono-ExtraCondensed.
288
+
289
+ The Noto family of fonts is freely available and developed by Google,
290
+ which describes Noto as:
291
+
292
+ > When text is rendered by a computer, sometimes characters are displayed as
293
+ > "tofu". They are little boxes to indicate your device doesn't have a
294
+ > font to display the text.
295
+ >
296
+ > Google has been developing a font family called Noto, which aims to support
297
+ > all languages with a harmonious look and feel. Noto is Google's answer to
298
+ > tofu. The name noto is to convey the idea that Google's goal is to see
299
+ > "no more tofu". Noto has multiple styles and weights, and is freely
300
+ > available to all.
301
+
302
+ Core tools used to produce this document:
303
+
304
+ - [Docker](https://www.docker.com/) provides a repeatable environment in
305
+ which to run the tools.
306
+ - [OCTool](https://github.com/jumanjihouse/octool)
307
+ provides a schema and wrapper to express compliance data as configuration.
308
+ - [Pandoc](https://pandoc.org/) converts extended markdown to PDF output.
309
+ - [Python](https://www.python.org/) is a core language for automation.
310
+ - [Ruby](https://www.ruby-lang.org/en/) is a core language for automation.
311
+ - [TeXLive](https://www.tug.org/texlive/) provides the \TeX\ family of tools.
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.6
4
+ version: 0.0.11
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-24 00:00:00.000000000 Z
11
+ date: 2020-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -93,61 +93,61 @@ dependencies:
93
93
  - !ruby/object:Gem::Version
94
94
  version: 2.19.0
95
95
  - !ruby/object:Gem::Dependency
96
- name: kwalify
96
+ name: json_pure
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
99
  - - '='
100
100
  - !ruby/object:Gem::Version
101
- version: 0.7.2
101
+ version: 2.3.0
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - '='
107
107
  - !ruby/object:Gem::Version
108
- version: 0.7.2
108
+ version: 2.3.0
109
109
  - !ruby/object:Gem::Dependency
110
- name: pandoc-ruby
110
+ name: kwalify
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - '='
114
114
  - !ruby/object:Gem::Version
115
- version: 2.1.4
115
+ version: 0.7.2
116
116
  type: :runtime
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
120
  - - '='
121
121
  - !ruby/object:Gem::Version
122
- version: 2.1.4
122
+ version: 0.7.2
123
123
  - !ruby/object:Gem::Dependency
124
- name: paru
124
+ name: pandoc-ruby
125
125
  requirement: !ruby/object:Gem::Requirement
126
126
  requirements:
127
127
  - - '='
128
128
  - !ruby/object:Gem::Version
129
- version: 0.4.0.1
129
+ version: 2.1.4
130
130
  type: :runtime
131
131
  prerelease: false
132
132
  version_requirements: !ruby/object:Gem::Requirement
133
133
  requirements:
134
134
  - - '='
135
135
  - !ruby/object:Gem::Version
136
- version: 0.4.0.1
136
+ version: 2.1.4
137
137
  - !ruby/object:Gem::Dependency
138
- name: recursive-open-struct
138
+ name: paru
139
139
  requirement: !ruby/object:Gem::Requirement
140
140
  requirements:
141
141
  - - '='
142
142
  - !ruby/object:Gem::Version
143
- version: 1.1.1
143
+ version: 0.4.0.1
144
144
  type: :runtime
145
145
  prerelease: false
146
146
  version_requirements: !ruby/object:Gem::Requirement
147
147
  requirements:
148
148
  - - '='
149
149
  - !ruby/object:Gem::Version
150
- version: 1.1.1
150
+ version: 0.4.0.1
151
151
  description:
152
152
  email: jumanjiman@gmail.com
153
153
  executables:
@@ -174,6 +174,10 @@ files:
174
174
  - schemas/v1.0.1/component.yaml
175
175
  - schemas/v1.0.1/config.yaml
176
176
  - schemas/v1.0.1/standard.yaml
177
+ - schemas/v1.0.2/certification.yaml
178
+ - schemas/v1.0.2/component.yaml
179
+ - schemas/v1.0.2/config.yaml
180
+ - schemas/v1.0.2/standard.yaml
177
181
  - templates/ssp.erb
178
182
  homepage: https://github.com/jumanjiman/octool
179
183
  licenses: