inspec_tools 2.0.1.pre2 → 2.0.1.pre3

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 (4) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/lib/inspec_tools/xlsx.rb +58 -36
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68a7bc23a335f2851633c7164898006ae7bd2526371194bff12c3b9b4592856c
4
- data.tar.gz: 85f62513a8af8009705cf8afd55a4c1ac55054e95c7a3f08cd1f587cf7d67c09
3
+ metadata.gz: 9821cf8b386c55599d08754287c0e15cf461c2cf1885e9c4e2006f89c560427b
4
+ data.tar.gz: b07b4ea7ab7f79da47fa1ef3fc2dc52c09d98a7f6a8b24e140d0ba47aae7d435
5
5
  SHA512:
6
- metadata.gz: e75e865855f24ff7013ec487bf11dc2c89c41f2b26968efb92376907f0b2fd7830cab6a2b140391ec8e1a146fbe3eef7a7aaa14e73e0e4f4d11933189942705f
7
- data.tar.gz: 388f8fc5b01af577ebc64b6ddcc760459a322bb1e6f49207ab3891c4f15f8c68cc00d5f0f19592473357d03c672085c8af1c1699a3ecfb4045e2135747071643
6
+ metadata.gz: b0375514656589efc9171cdc47d2106376a3da86b84e5eb6bf753c8778819784074204bfbc8763536cf4aa1c720236c9692527239d5c2250d0f881f3c882104b
7
+ data.tar.gz: ecaa2419766fa3fe9f1ad9722e029002b19eb2e080309e8aeb797ad501ffbcf86ad5da3cc8968bfb8be83268f381261c69ca911315981ca5e1e8f8e356aabf2a
data/CHANGELOG.md CHANGED
@@ -2,7 +2,15 @@
2
2
 
3
3
  ## [Unreleased](https://github.com/mitre/inspec_tools/tree/HEAD)
4
4
 
5
- [Full Changelog](https://github.com/mitre/inspec_tools/compare/v2.0.1.pre1...HEAD)
5
+ [Full Changelog](https://github.com/mitre/inspec_tools/compare/v2.0.1.pre2...HEAD)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Cleanup xlsx2inspec Process of Adding NIST and CIS Controls to Inspec Controls [\#127](https://github.com/mitre/inspec_tools/pull/127) ([Bialogs](https://github.com/Bialogs))
10
+
11
+ ## [v2.0.1.pre2](https://github.com/mitre/inspec_tools/tree/v2.0.1.pre2) (2020-04-02)
12
+
13
+ [Full Changelog](https://github.com/mitre/inspec_tools/compare/v2.0.1.pre1...v2.0.1.pre2)
6
14
 
7
15
  **Merged pull requests:**
8
16
 
@@ -13,11 +13,15 @@ require_relative '../utilities/inspec_util'
13
13
  module InspecTools
14
14
  # Methods for converting from XLS to various formats
15
15
  class XLSXTool
16
+ CIS_2_NIST_XLSX = Roo::Spreadsheet.open(File.join(File.dirname(__FILE__), '../data/NIST_Map_02052020_CIS_Controls_Version_7.1_Implementation_Groups_1.2.xlsx'))
17
+ LATEST_NIST_REV = 'Rev_4'.freeze
18
+
16
19
  def initialize(xlsx, mapping, name, verbose = false)
17
20
  @name = name
18
21
  @xlsx = xlsx
19
22
  @mapping = mapping
20
23
  @verbose = verbose
24
+ @cis_to_nist = get_cis_to_nist_control_mapping(CIS_2_NIST_XLSX)
21
25
  end
22
26
 
23
27
  def to_ckl
@@ -41,6 +45,18 @@ module InspecTools
41
45
 
42
46
  private
43
47
 
48
+ def get_cis_to_nist_control_mapping(spreadsheet)
49
+ cis_to_nist = {}
50
+ spreadsheet.sheet(3).each do |row|
51
+ if row[3].is_a? Numeric
52
+ cis_to_nist[row[3].to_s] = row[0]
53
+ else
54
+ cis2Nist[row[2].to_s] = row[0] unless (row[2] == '') || row[2].to_i.nil?
55
+ end
56
+ end
57
+ cis_to_nist
58
+ end
59
+
44
60
  def insert_json_metadata
45
61
  @profile['name'] = @name
46
62
  @profile['title'] = 'InSpec Profile'
@@ -59,67 +75,73 @@ module InspecTools
59
75
  end
60
76
 
61
77
  def parse_cis_controls(control_prefix)
62
- cis2NistXls = Roo::Spreadsheet.open(File.join(File.dirname(__FILE__), "../data/NIST_Map_02052020_CIS_Controls_Version_7.1_Implementation_Groups_1.2.xlsx"))
63
- cis2Nist = {}
64
- cis2NistXls.sheet(3).each do |row|
65
- if row[3].is_a? Numeric
66
- cis2Nist[row[3].to_s] = row[0]
67
- else
68
- cis2Nist[row[2].to_s] = row[0] unless (row[2] == "") || (row[2].to_i.nil?)
69
- end
70
- end
71
- [ 1, 2 ].each do |level|
78
+ [1, 2].each do |level|
72
79
  @xlsx.sheet(level).each_row_streaming do |row|
73
80
  if row[@mapping['control.id']].nil? || !/^\d+(\.?\d)*$/.match(row[@mapping['control.id']].formatted_value)
74
81
  next
75
82
  end
83
+
76
84
  tag_pos = @mapping['control.tags']
77
85
  control = {}
78
86
  control['tags'] = {}
79
- control['id'] = control_prefix + '-' + row[@mapping['control.id']].formatted_value unless @mapping['control.id'].nil? || row[@mapping['control.id']].nil?
80
- control['title'] = row[@mapping['control.title']].formatted_value unless @mapping['control.title'].nil? || row[@mapping['control.title']].nil?
81
- control['desc'] = ""
82
- control['desc'] = row[@mapping['control.desc']].formatted_value unless row[@mapping['control.desc']].nil?
83
- control['tags']['rationale'] = row[tag_pos['rationale']].formatted_value unless row[tag_pos['rationale']].empty?
87
+ control['id'] = control_prefix + '-' + row[@mapping['control.id']].formatted_value unless cell_empty?(@mapping['control.id']) || cell_empty?(row[@mapping['control.id']])
88
+ control['title'] = row[@mapping['control.title']].formatted_value unless cell_empty?(@mapping['control.title']) || cell_empty?(row[@mapping['control.title']])
89
+ control['desc'] = ''
90
+ control['desc'] = row[@mapping['control.desc']].formatted_value unless cell_empty?(row[@mapping['control.desc']])
91
+ control['tags']['rationale'] = row[tag_pos['rationale']].formatted_value unless cell_empty?(row[tag_pos['rationale']])
84
92
 
85
93
  control['tags']['severity'] = level == 1 ? 'medium' : 'high'
86
94
  control['impact'] = Utils::InspecUtil.get_impact(control['tags']['severity'])
87
- control['tags']['ref'] = row[@mapping['control.ref']].formatted_value unless @mapping['control.ref'].nil? || row[@mapping['control.ref']].nil?
95
+ control['tags']['ref'] = row[@mapping['control.ref']].formatted_value unless cell_empty?(@mapping['control.ref']) || cell_empty?(row[@mapping['control.ref']])
88
96
  control['tags']['cis_level'] = level unless level.nil?
89
97
 
90
- unless row[tag_pos['cis_controls']].empty?
98
+ unless cell_empty?(row[tag_pos['cis_controls']])
91
99
  # cis_control must be extracted from CIS control column via regex
92
- control = handle_cis_tags(control, row[tag_pos['cis_controls']].formatted_value.scan(/CONTROL:v(\d) (\d+)\.?(\d*)/))
100
+ cis_tags_array = row[tag_pos['cis_controls']].formatted_value.scan(/CONTROL:v(\d) (\d+)\.?(\d*)/).flatten
101
+ cis_tags = %i(revision section sub_section).zip(cis_tags_array).to_h
102
+ control = apply_cis_and_nist_controls(control, cis_tags)
93
103
  end
94
104
 
95
- control['tags']['cis_rid'] = row[@mapping['control.id']].formatted_value unless @mapping['control.id'].nil? || row[@mapping['control.id']].nil?
96
- control['tags']['check'] = row[tag_pos['check']].formatted_value unless tag_pos['check'].nil? || row[tag_pos['check']].empty?
97
- control['tags']['fix'] = row[tag_pos['fix']].formatted_value unless tag_pos['fix'].nil? || row[tag_pos['fix']].empty?
105
+ control['tags']['cis_rid'] = row[@mapping['control.id']].formatted_value unless cell_empty?(@mapping['control.id']) || cell_empty?(row[@mapping['control.id']])
106
+ control['tags']['check'] = row[tag_pos['check']].formatted_value unless cell_empty?(tag_pos['check']) || cell_empty?(row[tag_pos['check']])
107
+ control['tags']['fix'] = row[tag_pos['fix']].formatted_value unless cell_empty?(tag_pos['fix']) || cell_empty?(row[tag_pos['fix']])
98
108
 
99
109
  @controls << control
100
110
  end
101
111
  end
102
112
  end
103
113
 
104
- def handle_cis_tags(control, cis_tags)
105
- control['tags']['cis_controls'] = []
106
- control['tags']['nist'] = []
114
+ def cell_empty?(cell)
115
+ return cell.empty? if cell.respond_to?(:empty?)
107
116
 
108
- cis_tags.each do |cis_tag|
109
- if cis_tag[2].nil? || cis_tag[2] == ""
110
- control['tags']['cis_controls'] << cis_tag[1].to_s
111
- control['tags']['nist'] << cis2Nist[cis_tag[1]]
112
- else
113
- control['tags']['cis_controls'] << cis_tag[1].to_s + "." + cis_tag[2].to_s
114
- control['tags']['nist'] << cis2Nist[cis_tag[1].to_s + "." + cis_tag[2].to_s]
115
- end
116
- end
117
+ cell.nil?
118
+ end
119
+
120
+ def apply_cis_and_nist_controls(control, cis_tags)
121
+ control['tags']['cis_controls'], control['tags']['nist'] = [], []
117
122
 
118
- if not control['tags']['nist'].nil?
119
- control['tags']['nist'] << "Rev_4"
123
+ if cis_tags[:sub_section].nil? || cis_tags[:sub_section].blank?
124
+ control['tags']['cis_controls'] << cis_tags[:section]
125
+ control['tags']['nist'] << get_nist_control_for_cis([cis_tags[:section]])
126
+ else
127
+ control['tags']['cis_controls'] << "#{cis_tags[:section]}.#{cis_tags[:sub_section]}"
128
+ control['tags']['nist'] << get_nist_control_for_cis([cis_tags[:section], cis_tags[:sub_section]])
120
129
  end
121
- control['tags']['cis_controls'] << "Rev_" + cis_tags.first[0] unless cis_tags[0].nil?
130
+
131
+ control['tags']['nist'] << LATEST_NIST_REV unless control['tags']['nist'].nil?
132
+ control['tags']['cis_controls'] << "Rev_#{cis_tags[:revision]}" unless cis_tags[:revision].nil?
133
+
122
134
  control
123
135
  end
136
+
137
+ def get_nist_control_for_cis(section, sub_section=nil)
138
+ return @cis_to_nist[section] if sub_section.nil?
139
+
140
+ @cis_to_nist["#{section}.#{sub_section}"]
141
+ end
124
142
  end
125
143
  end
144
+
145
+ # rubocop:enable Metrics/AbcSize
146
+ # rubocop:enable Metrics/PerceivedComplexity
147
+ # rubocop:enable Metrics/CyclomaticComplexity
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1.pre2
4
+ version: 2.0.1.pre3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Thew
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2020-04-02 00:00:00.000000000 Z
14
+ date: 2020-04-03 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: colorize