Class: InspecDelta::Object::Control

Inherits:
Inspec::Object::Control
  • Object
show all
Defined in:
lib/inspec_delta/objects/control.rb

Overview

This class represents a modified representation of an Inspec Control

Constant Summary collapse

MAX_LINE_LENGTH =
120
WORD_WRAP_INDENT =
4

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeControl

Creates a new Control based on the Inspec Object Control definition



23
24
25
26
27
28
29
# File 'lib/inspec_delta/objects/control.rb', line 23

def initialize
  super

  @global_code = []
  @control_code = []
  @control_string = ''
end

Instance Attribute Details

#control_codeObject

Returns the value of attribute control_code.



18
19
20
# File 'lib/inspec_delta/objects/control.rb', line 18

def control_code
  @control_code
end

#control_stringObject (readonly)

Returns the value of attribute control_string.



19
20
21
# File 'lib/inspec_delta/objects/control.rb', line 19

def control_string
  @control_string
end

#global_codeObject

Returns the value of attribute global_code.



18
19
20
# File 'lib/inspec_delta/objects/control.rb', line 18

def global_code
  @global_code
end

Class Method Details

.benchmark_tagshash

Hash of tags we want to read from the benchmark

Returns:

  • (hash)

    benchmark_tags



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/inspec_delta/objects/control.rb', line 143

def self.benchmark_tags
  {
    'severity' => :severity,
    'gtitle' => :gtitle,
    'satisfies' => :satisfies,
    'gid' => :gid,
    'rid' => :rid,
    'stig_id' => :stig_id,
    'fix_id' => :fix_id,
    'cci' => :cci,
    'false_negatives' => :false_negatives,
    'false_positives' => :false_positives,
    'documentable' => :documentable,
    'mitigations' => :mitigations,
    'severity_override_guidance' => :severity_override_guidance,
    'potential_impacts' => :potential_impacts,
    'third_party_tools' => :third_party_tools,
    'mitigation_controls' => :mitigation_controls,
    'responsibility' => :responsibility,
    'ia_controls' => :ia_controls,
    'check' => :check,
    'fix' => :fix
  }
end

.from_benchmark(benchmark) ⇒ Control

Creates a new Control from a benchmark hash definition

Parameters:

  • benchmark (Hash)
    • Hash representation of a benchmark

Returns:

  • (Control)

    Control representation of the benchmark



173
174
175
176
177
178
179
180
181
182
183
# File 'lib/inspec_delta/objects/control.rb', line 173

def self.from_benchmark(benchmark)
  control = new
  control.descriptions[:default] = benchmark[:desc]
  control.id     = benchmark[:id]
  control.title  = benchmark[:title]
  control.impact = impact(benchmark[:severity])
  benchmark_tags.each do |tag, benchmark_key|
    control.add_tag(Inspec::Object::Tag.new(tag, benchmark[benchmark_key]))
  end
  control
end

.from_ruby(ruby_control_path) ⇒ Control

Creates a new Control from a ruby definition

Parameters:

  • ruby_control_path (String)
    • path to the ruby file that contains the control

Returns:

  • (Control)

    Control parsed from file



190
191
192
193
194
195
196
# File 'lib/inspec_delta/objects/control.rb', line 190

def self.from_ruby(ruby_control_path)
  control = new
  control_file_string = File.read(File.expand_path(ruby_control_path))
  send(:parse_ruby, control, RubyParser.new.parse(control_file_string))
  control.instance_variable_set(:@control_string, control_file_string)
  control
end

.impact(severity) ⇒ decimal, string

Converts the string severity into a decimal representation

Parameters:

  • severity (String)
    • string representation of the severity

Returns:

  • (decimal)

    numerical representation of the severity if match is found

  • (string)

    severity if no match is found



204
205
206
207
208
209
210
# File 'lib/inspec_delta/objects/control.rb', line 204

def self.impact(severity)
  {
    'low' => 0.3,
    'medium' => 0.5,
    'high' => 0.7
  }.fetch(severity) { severity }
end

Instance Method Details

#apply_updates(other) ⇒ control_string

Updates a string representation of a Control with string substitutions

Parameters:

  • other (Control)
    • The Control to be merged in

Returns:

  • (control_string)

    String updated string with the changes from other



36
37
38
39
40
41
42
# File 'lib/inspec_delta/objects/control.rb', line 36

def apply_updates(other)
  apply_updates_title(other.title)
  apply_updates_desc(other.descriptions[:default])
  apply_updates_impact(other.impact)
  apply_updates_tags(other)
  @control_string
end

#apply_updates_desc(desc) ⇒ Object

Updates a string representation of a Control’s description with string substitutions

Parameters:

  • desc (Control)
    • The description to be applied to the Control



61
62
63
64
65
66
67
68
69
70
# File 'lib/inspec_delta/objects/control.rb', line 61

def apply_updates_desc(desc)
  return if desc.to_s.empty?

  wrap_length = MAX_LINE_LENGTH - WORD_WRAP_INDENT

  @control_string.sub!(
    /desc\s+(((").*?(?<!\\)")|((').*?(?<!\\)')|((%q{).*?(?<!\\)[}])|(nil))\n/m,
    "desc %q{#{desc}}".word_wrap(wrap_length).indent(WORD_WRAP_INDENT)
  )
end

#apply_updates_impact(impact) ⇒ Object

Updates a string representation of a Control’s impact with string substitutions

Parameters:

  • impact (Decimal)
    • The impact to be applied to the Control



75
76
77
78
79
# File 'lib/inspec_delta/objects/control.rb', line 75

def apply_updates_impact(impact)
  return if impact.nil?

  @control_string.sub!(/impact\s+\d\.\d/, "impact #{impact}")
end

#apply_updates_tags(other) ⇒ Object

Updates a string representation of a Control’s tags with string substitutions

Parameters:

  • other (Control)
    • The Control to be merged in



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/inspec_delta/objects/control.rb', line 84

def apply_updates_tags(other)
  other.tags.each do |ot|
    tag = @tags.detect { |t| t.key == ot.key }
    next unless tag

    if ot.value.instance_of?(String)
      apply_updates_tags_string(ot)
    elsif ot.value.instance_of?(Array)
      apply_updates_tags_array(ot)
    elsif ot.value.instance_of?(FalseClass) || ot.value.instance_of?(TrueClass)
      apply_updates_tags_bool(ot)
    end
  end
end

#apply_updates_tags_array(tag) ⇒ Object

Updates a string representation of a Control’s tags with string substitutions

Parameters:

  • ot (Tag)
    • The Tag to be merged in



121
122
123
124
125
126
127
128
# File 'lib/inspec_delta/objects/control.rb', line 121

def apply_updates_tags_array(tag)
  wrap_length = MAX_LINE_LENGTH - WORD_WRAP_INDENT

  @control_string.sub!(
    /tag\s+['"]?#{tag.key}['"]?:\s+(((%w\().*?(?<!\\)(\)))|((\[).*?(?<!\\)(\]))|(nil))\n/m,
    "tag '#{tag.key}': #{tag.value}".word_wrap(wrap_length).indent(WORD_WRAP_INDENT)
  )
end

#apply_updates_tags_bool(tag) ⇒ Object

Updates a string representation of a Control’s tags with string substitutions

Parameters:

  • ot (Tag)
    • The Tag to be merged in



133
134
135
136
137
138
# File 'lib/inspec_delta/objects/control.rb', line 133

def apply_updates_tags_bool(tag)
  @control_string.sub!(
    /tag\s+['"]?#{tag.key}['"]?:\s+(true|false|'')\n/,
    "tag '#{tag.key}': #{tag.value}\n"
  )
end

#apply_updates_tags_string(tag) ⇒ Object

Updates a string representation of a Control’s tags with string substitutions

Parameters:

  • ot (Tag)
    • The Tag to be merged in



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/inspec_delta/objects/control.rb', line 102

def apply_updates_tags_string(tag)
  if tag.value.empty?
    @control_string.sub!(
      /tag\s+['"]?#{tag.key}['"]?:\s+(((").*?(?<!\\)")|((').*?(?<!\\)')|((%q{).*?(?<!\\)[}])|(nil))\n/m,
      "tag '#{tag.key}': nil\n"
    )
  else
    wrap_length = MAX_LINE_LENGTH - WORD_WRAP_INDENT

    @control_string.sub!(
      /tag\s+['"]?#{tag.key}['"]?:\s+(((").*?(?<!\\)")|((').*?(?<!\\)')|((%q{).*?(?<!\\)[}])|(nil))\n/m,
      "tag '#{tag.key}': %q{#{tag.value}}".word_wrap(wrap_length).indent(WORD_WRAP_INDENT)
    )
  end
end

#apply_updates_title(title) ⇒ Object

Updates a string representation of a Control’s title with string substitutions

Parameters:

  • title (String)
    • The title to be applied to the Control



47
48
49
50
51
52
53
54
55
56
# File 'lib/inspec_delta/objects/control.rb', line 47

def apply_updates_title(title)
  return if title.to_s.empty?

  wrap_length = MAX_LINE_LENGTH - WORD_WRAP_INDENT

  @control_string.sub!(
    /title\s+(((").*?(?<!\\)")|((').*?(?<!\\)')|((%q{).*?(?<!\\)[}])|(nil))\n/m,
    "title %q{#{title}}".word_wrap(wrap_length).indent(WORD_WRAP_INDENT)
  )
end

#merge_from(other) ⇒ Control

Merges another controll into self

Currently we are only mergings objects from the base Inspec::Objects::Control as that is what will be used for updated STIG merges id is not updated as that should be the unique identifier

Parameters:

  • other (Control)
    • another control to take values from.

Returns:

  • (Control)

    self - updated with values from other control



221
222
223
224
225
226
227
228
229
230
# File 'lib/inspec_delta/objects/control.rb', line 221

def merge_from(other)
  @title = other.title unless other.title.to_s.empty?
  @descriptions[:default] = other.descriptions[:default] unless other.descriptions[:default].to_s.empty?
  @impact = other.impact unless other.impact.nil?
  other.tags.each do |ot|
    tag = @tags.detect { |t| t.key == ot.key }
    tag ? tag.value = ot.value : @tags.push(ot)
  end
  self
end

#to_rubystring

Converts the Control object into a string representation of a Ruby Object

unable to use the super function as it is already converted to a string

Returns:

  • (string)

    the control as a ruby string



366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/inspec_delta/objects/control.rb', line 366

def to_ruby
  res = []
  res.push global_code unless global_code.empty?
  res.push "control #{id.inspect} do"
  res.push "  title #{title.inspect}" unless title.to_s.empty?
  res.push "  desc  #{descriptions[:default].inspect}" unless descriptions[:default].to_s.empty?
  res.push "  impact #{impact}" unless impact.nil?
  tags.each do |t|
    res.push("  #{t.to_ruby}")
  end
  res.push control_code unless control_code.empty?
  res.push 'end'
  res.join("\n")
end