Skip to content

Commit db95fcb

Browse files
authored
VULCAN-559: Support for Multiple CCIs (#569)
* Reading ccis from the imported spreadsheet Refactored getting nist_control_family to accomodate for instances of multi ccis Refactored inspec code to accomodate for instances of multi ccis Signed-off-by: Vanessa Fotso <[email protected]> * Sort and format rule.ident beforre saving Rspec test for rules with multiple CCI Signed-off-by: Vanessa Fotso <[email protected]> --------- Signed-off-by: Vanessa Fotso <[email protected]>
1 parent 85b9164 commit db95fcb

File tree

5 files changed

+35
-6
lines changed

5 files changed

+35
-6
lines changed

app/constants/import_constants.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ module ImportConstants
1717
OPTIONAL_MAPPING_CONSTANTS = {
1818
vendor_comments: 'Vendor Comments',
1919
mitigation: 'Mitigation',
20-
inspec_control_body: 'InSpec Control Body'
20+
inspec_control_body: 'InSpec Control Body',
21+
ident: 'CCI'
2122
}.freeze
2223

2324
IMPORT_MAPPING = REQUIRED_MAPPING_CONSTANTS.merge(OPTIONAL_MAPPING_CONSTANTS)

app/models/base_rule.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ def as_json(options = {})
7676
end
7777

7878
def nist_control_family
79-
CCI_TO_NIST_CONSTANT[ident&.to_sym]
79+
ccis = ident.to_s.split(/, */)
80+
ia_controls = []
81+
ccis.each { |cci| ia_controls << CCI_TO_NIST_CONSTANT[cci.to_sym] }
82+
ia_controls.uniq.join(', ')
8083
end
8184

8285
private

app/models/component.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ def from_spreadsheet(spreadsheet)
150150
r.srg_rule_id = srg_rule.id
151151
# Get the inspec control body if provided
152152
r.inspec_control_body = row[IMPORT_MAPPING[:inspec_control_body]]
153+
# It's possible to have multiple cci on the spreadsheet. Parse cci from the spreadsheet.
154+
r.ident = row[IMPORT_MAPPING[:ident]]
153155

154156
disa_rule_description = r.disa_rule_descriptions.first
155157
disa_rule_description.vuln_discussion = row[IMPORT_MAPPING[:vuln_discussion]]

app/models/rule.rb

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class Rule < BaseRule
3939

4040
before_validation :set_rule_id
4141
before_save :apply_audit_comment
42-
before_save :update_inspec_code
42+
before_save :sort_ident, :update_inspec_code
4343
before_destroy :prevent_destroy_if_under_review_or_locked
4444
after_destroy :update_component_rules_count
4545
after_save :update_component_rules_count
@@ -218,9 +218,8 @@ def update_inspec_code
218218
control.add_tag(Inspec::Object::Tag.new('gid', "V-#{component[:prefix]}-#{rule_id}"))
219219
control.add_tag(Inspec::Object::Tag.new('rid', "SV-#{component[:prefix]}-#{rule_id}"))
220220
control.add_tag(Inspec::Object::Tag.new('stig_id', "#{component[:prefix]}-#{rule_id}"))
221-
control.add_tag(Inspec::Object::Tag.new('cci', ([ident] + satisfies.pluck(:ident)).uniq.sort)) if ident.present?
222-
control.add_tag(Inspec::Object::Tag.new('nist', ([nist_control_family] +
223-
satisfies.map(&:nist_control_family)).uniq.sort))
221+
control.add_tag(Inspec::Object::Tag.new('cci', format_inspec_control_cci.uniq.sort)) if ident.present?
222+
control.add_tag(Inspec::Object::Tag.new('nist', format_inspec_control_nist.uniq.sort))
224223
if desc.present?
225224
%i[false_negatives false_positives documentable mitigations severity_override_guidance potential_impacts
226225
third_party_tools mitigation_control responsibility ia_controls].each do |field|
@@ -251,6 +250,22 @@ def basic_fields
251250

252251
private
253252

253+
def sort_ident
254+
self.ident = ident.to_s.split(/, */).uniq.sort.join(', ')
255+
end
256+
257+
def format_inspec_control_cci
258+
rule_cci = ident.split(/, */)
259+
satisfies_cci = satisfies.pluck(:ident).map { |cci| cci.split(/, */) }.flatten
260+
rule_cci + satisfies_cci
261+
end
262+
263+
def format_inspec_control_nist
264+
rule_nist = nist_control_family.split(/, */)
265+
statisfies_nist = satisfies.map(&:nist_control_family).map { |nist| nist.split(/, */) }.flatten
266+
rule_nist + statisfies_nist
267+
end
268+
254269
def single_rule_clone?
255270
@single_rule_clone
256271
end

spec/models/rules_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,12 @@
260260
@p1r1.reload
261261
end
262262
end
263+
264+
context 'rule with multiple ident' do
265+
it 'should have a unique string list of cci sorted in ascending order' do
266+
@p1r1.ident = 'CCI-000068, CCI-000054, CCI-000054'
267+
@p1r1.save!
268+
expect(@p1r1.ident).to eq('CCI-000054, CCI-000068')
269+
end
270+
end
263271
end

0 commit comments

Comments
 (0)