Class: Inspec::Rule

Inherits:
Object
  • Object
show all
Includes:
RSpec::Matchers
Defined in:
lib/inspec/rule.rb

Overview

rubocop:disable Metrics/ClassLength

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, _opts, &block) ⇒ Rule

Returns a new instance of Rule.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/inspec/rule.rb', line 15

def initialize(id, _opts, &block)
  @id = id
  @impact = nil
  @title = nil
  @desc = nil
  @refs = []
  @tags = {}

  # not changeable by the user:
  @__block = block
  @__code = __get_block_source(&block)
  @__source_location = __get_block_source_location(&block)
  @__rule_id = nil
  @__checks = []
  @__skip_rule = nil

  # evaluate the given definition
  instance_eval(&block) if block_given?
end

Class Method Details

.checks(rule) ⇒ Object



122
123
124
# File 'lib/inspec/rule.rb', line 122

def self.checks(rule)
  rule.instance_variable_get(:@__checks)
end

.full_id(profile_id, rule) ⇒ Object

Get the full id consisting of profile id + rule id for the rule. If the rule’s profile id is empty, the given profile_id will be used instead and also set for the rule.



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/inspec/rule.rb', line 174

def self.full_id(profile_id, rule)
  if rule.is_a?(String) or rule.nil?
    rid = rule
  else
    # As the profile context is exclusively pulled with a
    # profile ID, attach it to the rule if necessary.
    rid = rule.instance_variable_get(:@id)
    if rid.nil?
      # TODO: Message about skipping this rule
      # due to missing ID
      return nil
    end
  end
  pid = rule_id(rule)
  pid = set_rule_id(rule, profile_id) if pid.nil?

  # if we don't have a profile id, just return the rule's ID
  return rid if pid.nil? or pid.empty?
  # otherwise combine them
  "#{pid}/#{rid}"
end

.merge(dst, src) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/inspec/rule.rb', line 146

def self.merge(dst, src)
  if src.id != dst.id
    # TODO: register an error, this case should not happen
    return
  end
  sp = rule_id(src)
  dp = rule_id(dst)
  if sp != dp
    # TODO: register an error, this case should not happen
    return
  end
  # merge all fields
  dst.impact(src.impact) unless src.impact.nil?
  dst.title(src.title)   unless src.title.nil?
  dst.desc(src.desc)     unless src.desc.nil?
  # merge indirect fields
  # checks defined in the source will completely eliminate
  # all checks that were defined in the destination
  sc = checks(src)
  dst.instance_variable_set(:@__checks, sc) unless sc.empty?
  sr = skip_status(src)
  set_skip_rule(dst, sr) unless sr.nil?
end

.prepare_checks(rule) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
# File 'lib/inspec/rule.rb', line 134

def self.prepare_checks(rule)
  msg = skip_status(rule)
  return checks(rule) unless msg
  msg = 'Skipped control due to only_if condition.' if msg == true

  # TODO: we use os as the carrier here, but should consider
  # a separate resource to do skipping
  resource = rule.os
  resource.skip_resource(msg)
  [['describe', [resource], nil]]
end

.rule_id(rule) ⇒ Object



114
115
116
# File 'lib/inspec/rule.rb', line 114

def self.rule_id(rule)
  rule.instance_variable_get(:@__rule_id)
end

.set_rule_id(rule, value) ⇒ Object



118
119
120
# File 'lib/inspec/rule.rb', line 118

def self.set_rule_id(rule, value)
  rule.instance_variable_set(:@__rule_id, value)
end

.set_skip_rule(rule, value) ⇒ Object



130
131
132
# File 'lib/inspec/rule.rb', line 130

def self.set_skip_rule(rule, value)
  rule.instance_variable_set(:@__skip_rule, value)
end

.skip_status(rule) ⇒ Object



126
127
128
# File 'lib/inspec/rule.rb', line 126

def self.skip_status(rule)
  rule.instance_variable_get(:@__skip_rule)
end

Instance Method Details

#desc(v = nil) ⇒ Object



50
51
52
53
# File 'lib/inspec/rule.rb', line 50

def desc(v = nil)
  @desc = unindent(v) unless v.nil?
  @desc
end

#describe(*values, &block) ⇒ nil|DescribeBase

Describe will add one or more tests to this control. There is 2 ways of calling it:

describe resource do ... end

or

describe.one do ... end

Parameters:

  • Resource (any)

    to be describe, string, or nil

  • An (Proc)

    optional block containing tests for the described resource

Returns:

  • (nil|DescribeBase)

    if called without arguments, returns DescribeBase



97
98
99
100
101
102
103
104
105
106
# File 'lib/inspec/rule.rb', line 97

def describe(*values, &block)
  if values.empty? && !block_given?
    dsl = self.class.ancestors[1]
    Class.new(DescribeBase) do
      include dsl
    end.new(method(:__add_check))
  else
    __add_check('describe', values, block)
  end
end

#expect(value, &block) ⇒ Object



108
109
110
111
112
# File 'lib/inspec/rule.rb', line 108

def expect(value, &block)
  target = Inspec::Expect.new(value, &block)
  __add_check('expect', [value], target)
  target
end

#id(*_) ⇒ Object



35
36
37
38
# File 'lib/inspec/rule.rb', line 35

def id(*_)
  # never overwrite the ID
  @id
end

#impact(v = nil) ⇒ Object



40
41
42
43
# File 'lib/inspec/rule.rb', line 40

def impact(v = nil)
  @impact = v unless v.nil?
  @impact
end

#only_ifnil

Skip all checks if only_if is false

Parameters:

  • &block (Type)

    returns true if tests are added, false otherwise

Returns:

  • (nil)


80
81
82
83
# File 'lib/inspec/rule.rb', line 80

def only_if
  return unless block_given?
  @__skip_rule ||= !yield
end

#ref(ref = nil, opts = {}) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/inspec/rule.rb', line 55

def ref(ref = nil, opts = {})
  return @refs if ref.nil? && opts.empty?
  if opts.empty? && ref.is_a?(Hash)
    opts = ref
  else
    opts[:ref] = ref
  end
  @refs.push(opts)
end

#tag(*args) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/inspec/rule.rb', line 65

def tag(*args)
  args.each do |arg|
    if arg.is_a?(Hash)
      @tags.merge!(arg)
    else
      @tags[arg] ||= nil
    end
  end
  @tags
end

#title(v = nil) ⇒ Object



45
46
47
48
# File 'lib/inspec/rule.rb', line 45

def title(v = nil)
  @title = v unless v.nil?
  @title
end