mitre-inspec-objects 0.3.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9d65c4605033c4239780e56b8a9084d8f7fa9cdb2a971ba9062b9657a788949a
4
+ data.tar.gz: 226d6194461b806d249dbc188bc1cda532973f60c06d53dd0c1a5c75558a5f5f
5
+ SHA512:
6
+ metadata.gz: 289530d31dd264f8b2339f09b8ea55858d644fd91cb48420ff4b9e269a2566b726aaee50e6849428b5f2c8fc23ec35cb240d486b6f428868dc83d4cb0918a7d8
7
+ data.tar.gz: 2468c9a73f7f5bfa729fe0b6b8b2d96a62ebfa1d99e122976d070ce716a41de3839eba843c171de27fab5c985087d5b04a7300a485cd8df2c9e1315318594ed8
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "mitre-inspec-objects", path: "."
6
+
7
+ group :test do
8
+ gem "chef-utils", "~> 16.6.14"
9
+ gem "chefstyle", "0.13.0"
10
+ gem "minitest", "~> 5.5"
11
+ gem "rake", ">= 10"
12
+ end
data/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # inspec-objects
2
+ [![Gem Version](https://badge.fury.io/rb/mitre-inspec-objects.svg)](https://badge.fury.io/rb/mitre-inspec-objects)
3
+
4
+ **Umbrella Project**: [InSpec](https://github.com/chef/chef-oss-practices/blob/master/projects/inspec.md)
5
+
6
+ **Project State**: [Maintained](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md#maintained)
7
+
8
+ **Issues [Response Time Maximum](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)**: None
9
+
10
+ **Pull Request [Response Time Maximum](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)**: None
11
+
12
+ These classes were migrated out of InSpec, specifically [inspec/lib/objects](https://github.com/inspec/inspec/tree/master/lib/inspec/objects).
13
+
14
+ InSpec does not uses these classes directly. They can be used to programmatically create InSpec profiles.
15
+
16
+ No further documentation or support is available.
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class Control
5
+ attr_accessor :header, :id, :title, :descriptions, :impact, :tests, :post_body, :tags, :refs, :only_if
6
+ def initialize
7
+ @header = ""
8
+ @tests = []
9
+ @tags = []
10
+ @refs = []
11
+ @descriptions = {}
12
+ @post_body = ""
13
+ end
14
+
15
+ def add_header(header)
16
+ @header = header
17
+ end
18
+
19
+ def add_test(t)
20
+ @tests.push(t)
21
+ end
22
+
23
+ def add_tag(t)
24
+ @tags.push(t)
25
+ end
26
+
27
+ def add_post_body(post_body)
28
+ @post_body = post_body
29
+ end
30
+
31
+ def to_hash
32
+ {
33
+ header: header,
34
+ id: id,
35
+ title: title,
36
+ descriptions: descriptions,
37
+ impact: impact,
38
+ tests: tests.map(&:to_hash),
39
+ tags: tags.map(&:to_hash),
40
+ post_body: post_body,
41
+ }
42
+ end
43
+
44
+ def to_ruby
45
+ res = []
46
+ res.push header unless header.nil? || header.empty?
47
+ res.push "control #{id.inspect} do"
48
+ res.push " title #{title.inspect}" unless title.to_s.empty?
49
+ descriptions.each do |label, text|
50
+ if label == :default
51
+ next if text.nil? || (text == "") # don't render empty/nil desc
52
+
53
+ res.push " desc #{prettyprint_text(text, 2)}"
54
+ else
55
+ res.push " desc #{label.to_s.inspect}, #{prettyprint_text(text, 2)}"
56
+ end
57
+ end
58
+ res.push " impact #{impact}" unless impact.nil?
59
+ tags.each { |t| res.push(indent(t.to_ruby, 2)) }
60
+ refs.each { |t| res.push(" ref #{print_ref(t)}") }
61
+ res.push " only_if { #{only_if} }" if only_if
62
+ tests.each { |t| res.push(indent(t.to_ruby, 2)) }
63
+ res.push(indent(post_body, 2)) unless post_body.nil? || post_body.empty?
64
+ res.push "end"
65
+ res.join("\n")
66
+ end
67
+
68
+ private
69
+
70
+ def print_ref(x)
71
+ return x.inspect if x.is_a?(String)
72
+ raise "Cannot process the ref: #{x}" unless x.is_a?(Hash)
73
+
74
+ "(" + x.inspect + ")"
75
+ end
76
+
77
+ # Pretty-print a text block of InSpec code
78
+ #
79
+ # @param s [String] should not be empty
80
+ # @param depth [Int] indentation length for multiline text blocks
81
+ # @return [String] pretty-printed textblock
82
+ def prettyprint_text(s, depth)
83
+ txt = s.to_s.inspect.gsub('\n', "\n")
84
+ return txt unless txt.include?("\n")
85
+
86
+ middle = indent(txt[1..-2], depth + 2)
87
+ txt[0] + "\n" + middle + "\n" + " " * depth + txt[-1]
88
+ end
89
+
90
+ def indent(txt, d)
91
+ dt = " " * d
92
+ dt + txt.gsub("\n", "\n" + dt)
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class Describe
5
+ # Internal helper to structure test objects.
6
+ # Should not be exposed to the user as it is hidden behind
7
+ # `add_test`, `to_hash`, and `to_ruby` in Inspec::Object::Describe
8
+ Test = Struct.new(:its, :matcher, :expectation, :negated) do
9
+ def negate!
10
+ self.negated = !negated
11
+ end
12
+
13
+ def to_ruby
14
+ itsy = "it"
15
+ unless its.nil?
16
+ itsy = if its.is_a? Array
17
+ "its(" + its.inspect + ")"
18
+ else
19
+ "its(" + its.to_s.inspect + ")"
20
+ end
21
+ end
22
+ naughty = negated ? "_not" : ""
23
+ xpect = if expectation.nil?
24
+ ""
25
+ elsif expectation.class == Regexp
26
+ # without this, xpect values like / \/zones\// will not be parsed properly
27
+ "(#{expectation.inspect})"
28
+ else
29
+ " " + expectation.inspect
30
+ end
31
+ format("%s { should%s %s%s }", itsy, naughty, matcher, xpect)
32
+ end
33
+ end
34
+
35
+ # A qualifier describing the resource that will be tested. It may consist
36
+ # of the resource identification and multiple accessors to pinpoint the data
37
+ # the user wants to test.
38
+ attr_accessor :qualifier
39
+
40
+ # An array of individual tests for the qualifier. Every entry will be
41
+ # translated into an `it` or `its` clause.
42
+ attr_accessor :tests
43
+
44
+ # Optional variables which are used by tests.
45
+ attr_accessor :variables
46
+
47
+ # Optional method to skip this describe block altogether. If `skip` is
48
+ # defined it takes precendence and will print the skip statement instead
49
+ # of adding other tests.
50
+ attr_accessor :skip
51
+
52
+ include RubyHelper
53
+
54
+ def initialize
55
+ @qualifier = []
56
+ @tests = []
57
+ @variables = []
58
+ end
59
+
60
+ def add_test(its, matcher, expectation, opts = {})
61
+ test = Inspec::Object::Describe::Test.new(its, matcher, expectation, opts[:negated])
62
+ tests.push(test)
63
+ test
64
+ end
65
+
66
+ def to_ruby
67
+ return rb_skip unless skip.nil?
68
+
69
+ rb_describe
70
+ end
71
+
72
+ def to_hash
73
+ { qualifier: qualifier, tests: tests.map(&:to_h), variables: variables, skip: skip }
74
+ end
75
+
76
+ def resource
77
+ return if qualifier.empty? || qualifier[0].empty? || qualifier[0][0].empty?
78
+
79
+ qualifier[0][0]
80
+ end
81
+
82
+ private
83
+
84
+ def rb_describe
85
+ vars = variables.map(&:to_ruby).join("\n")
86
+ vars += "\n" unless vars.empty?
87
+
88
+ objarr = @qualifier
89
+ objarr = [["unknown object".inspect]] if objarr.nil? || objarr.empty?
90
+ obj = objarr.map { |q| ruby_qualifier(q) }.join(".")
91
+
92
+ rbtests = tests.map(&:to_ruby).join("\n ")
93
+ format("%sdescribe %s do\n %s\nend", vars, obj, rbtests)
94
+ end
95
+
96
+ def rb_skip
97
+ obj = @qualifier || skip.inspect
98
+ format("describe %s do\n skip %s\nend", obj, skip.inspect)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class EachLoop < List
5
+ attr_reader :variables
6
+ attr_accessor :tests
7
+ def initialize
8
+ super
9
+ @tests = []
10
+ @variables = []
11
+ end
12
+
13
+ def add_test(t = nil)
14
+ t ||= Test.new
15
+ t.qualifier[0] = ["entry"]
16
+ @tests.push(t)
17
+ t
18
+ end
19
+
20
+ def negate!
21
+ @tests.each(&:negate!)
22
+ end
23
+
24
+ def to_hash
25
+ { qualifier: qualifier, test: @test }
26
+ end
27
+
28
+ def to_ruby
29
+ vars = variables.map(&:to_ruby).join("\n")
30
+ vars += "\n" unless vars.empty?
31
+ obj = super
32
+ all_tests = @tests.map(&:to_ruby).join("\n").gsub("\n", "\n ")
33
+ format("%s%s.each do |entry|\n %s\nend", vars, obj, all_tests)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class Header
5
+ attr_accessor :header
6
+
7
+ def initialize(header)
8
+ @header = header
9
+ end
10
+
11
+ def to_hash
12
+ {
13
+ header: header,
14
+ }
15
+ end
16
+
17
+ def to_ruby
18
+ header.inspect.to_s
19
+ end
20
+
21
+ def to_s
22
+ "Header #{header}"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "inspec/input"
4
+
5
+ module Inspec::Object
6
+ class Input < ::Inspec::Input
7
+ # NOTE: No initialize method or accessors for the reasons listed above
8
+
9
+ #--------------------------------------------------------------------------#
10
+ # Marshalling
11
+ #--------------------------------------------------------------------------#
12
+
13
+ def to_hash
14
+ as_hash = { name: name, options: {} }
15
+ %i{description title identifier type required value}.each do |field|
16
+ val = send(field)
17
+ next if val.nil?
18
+
19
+ as_hash[:options][field] = val
20
+ end
21
+ as_hash
22
+ end
23
+
24
+ def ruby_var_identifier
25
+ identifier || "attr_" + name.downcase.strip.gsub(/\s+/, "-").gsub(/[^\w-]/, "")
26
+ end
27
+
28
+ def to_ruby
29
+ res = ["#{ruby_var_identifier} = attribute('#{name}',{"]
30
+ res.push " title: '#{title}'," unless title.to_s.empty?
31
+ res.push " value: #{value.inspect}," unless value.to_s.empty?
32
+ # to_ruby may generate code that is to be used by older versions of inspec.
33
+ # Anything older than 3.4 will not recognize the value: option, so
34
+ # send the default: option as well. See #3759
35
+ res.push " default: #{value.inspect}," unless value.to_s.empty?
36
+ res.push " description: '#{description}'," unless description.to_s.empty?
37
+ res.push "})"
38
+ res.join("\n")
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class List < Value
5
+ def map
6
+ raise "Inspec::Object::List.map needs to be called with a block" unless block_given?
7
+
8
+ t = List.new
9
+ t.qualifier = [["x"]]
10
+ yield(t)
11
+ return if t.qualifier == [["x"]]
12
+
13
+ @qualifier.push(["map", "{ |x| #{t.to_ruby} }"])
14
+ self
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class OrTest
5
+ attr_reader :tests
6
+ def initialize(tests)
7
+ @tests = tests
8
+ @negated = false
9
+ end
10
+
11
+ def skip
12
+ nil
13
+ end
14
+
15
+ def negate!
16
+ @negated = !@negated
17
+ end
18
+
19
+ def to_ruby
20
+ if @negated
21
+ # We don't use the describe.one wrapper when negated because:
22
+ # !(test1 || test2) same as (!test1 && !test2) where && is implicit in inspec
23
+ @tests.map do |test|
24
+ test.negate!
25
+ test
26
+ end.map(&:to_ruby).join("\n")
27
+
28
+ else
29
+ all_tests = @tests.map(&:to_ruby).join("\n").gsub("\n", "\n ")
30
+
31
+ format("describe.one do\n %s\nend", all_tests)
32
+ end
33
+ end
34
+
35
+ def to_hash
36
+ { describe_one: @tests.map(&:to_hash) }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class PostBody
5
+ attr_accessor :post_body
6
+
7
+ def initialize(post_body)
8
+ @post_body = post_body
9
+ end
10
+
11
+ def to_hash
12
+ {
13
+ post_body: post_body,
14
+ }
15
+ end
16
+
17
+ def to_ruby
18
+ post_body.inspect.to_s
19
+ end
20
+
21
+ def to_s
22
+ "Post Body #{post_body}"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ module RubyHelper
5
+ def ruby_qualifier(q)
6
+ if q.length <= 1
7
+ q[0]
8
+ elsif q[0] == "map" && q.length == 2
9
+ q[0] + " " + q[1]
10
+ else
11
+ q[0] + "(" + q[1..-1].map(&:inspect).join(", ") + ")"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class Tag
5
+ attr_accessor :key, :value
6
+
7
+ def initialize(key, value)
8
+ @key = key
9
+ @value = value
10
+ end
11
+
12
+ def to_hash
13
+ {
14
+ name: key,
15
+ value: value,
16
+ }
17
+ end
18
+
19
+ def to_ruby
20
+ "tag #{key}: #{value.inspect}"
21
+ end
22
+
23
+ def to_s
24
+ "Tag #{key} with #{value}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class Test
5
+ attr_accessor :qualifier, :matcher, :expectation, :skip, :negated, :variables, :only_if
6
+ include RubyHelper
7
+
8
+ def initialize
9
+ @qualifier = []
10
+ @negated = false
11
+ @variables = []
12
+ end
13
+
14
+ def negate!
15
+ @negated = !@negated
16
+ end
17
+
18
+ def to_ruby
19
+ return rb_skip unless skip.nil?
20
+
21
+ rb_describe
22
+ end
23
+
24
+ def to_hash
25
+ { qualifier: qualifier, matcher: matcher, expectation: expectation, skip: skip, negated: negated }
26
+ end
27
+
28
+ def resource
29
+ @resource ||=
30
+ if qualifier.empty? || qualifier[0].empty? || qualifier[0][0].empty?
31
+ nil
32
+ else
33
+ qualifier[0][0]
34
+ end
35
+ end
36
+
37
+ def remove_expectation
38
+ remove_instance_variable(:@expectation)
39
+ end
40
+
41
+ private
42
+
43
+ def describe_chain
44
+ return if @qualifier.empty?
45
+
46
+ resource = @qualifier.length > 1 ? @qualifier[0..-2] : [@qualifier[0]]
47
+ res = resource.map { |q| ruby_qualifier(q) }.join(".")
48
+ xres = nil
49
+
50
+ if @qualifier.length > 1
51
+ last = @qualifier[-1]
52
+ last_call = last.is_a?(Array) ? last[0].to_s : ""
53
+ if last.length == 1 && last_call !~ /^to_.$/ && !last_call.include?("[") && !last_call.empty?
54
+ # this will go in its()
55
+ xres = last_call
56
+ else
57
+ res += "." + ruby_qualifier(last) unless last_call.empty?
58
+ end
59
+ end
60
+
61
+ [res, xres]
62
+ end
63
+
64
+ def rb_describe
65
+ only_if_clause = "only_if { #{only_if} }\n" if only_if
66
+ vars = variables.map(&:to_ruby).join("\n")
67
+ vars += "\n" unless vars.empty?
68
+ res, xtra = describe_chain
69
+ itsy = xtra.nil? ? "it" : "its(" + xtra.to_s.inspect + ")"
70
+ naughty = @negated ? "_not" : ""
71
+ xpect = if !defined?(@expectation)
72
+ ""
73
+ elsif @expectation.class == Regexp
74
+ # without this, xpect values like / \/zones\// will not be parsed properly
75
+ "(#{@expectation.inspect})"
76
+ elsif xpect != ""
77
+ " " + expectation.inspect
78
+ end
79
+ format("%s%sdescribe %s do\n %s { should%s %s%s }\nend",
80
+ only_if_clause, vars, res, itsy, naughty, matcher, xpect)
81
+ end
82
+
83
+ def rb_skip
84
+ dc = describe_chain
85
+ obj = dc.nil? ? skip.inspect : dc[0]
86
+ format("describe %s do\n skip %s\nend", obj, skip.inspect)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec::Object
4
+ class Value
5
+ include ::Inspec::Object::RubyHelper
6
+
7
+ attr_accessor :qualifier
8
+ attr_accessor :skip
9
+ attr_accessor :variable
10
+
11
+ def initialize(qualifiers = [])
12
+ @qualifier = qualifiers
13
+ @variable = nil
14
+ end
15
+
16
+ def to_ruby
17
+ res = @variable.nil? ? "" : "#{@variable} = "
18
+ res + @qualifier.map { |x| ruby_qualifier(x) }.join(".")
19
+ end
20
+
21
+ def name_variable(cache = [])
22
+ @variable = Array("a".."z").find { |x| !cache.include?(x) }
23
+ cache.push(@variable)
24
+ @variable
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Inspec
4
+ module Object
5
+ require_relative "objects/tag"
6
+ require_relative "objects/control"
7
+ require_relative "objects/ruby_helper"
8
+ require_relative "objects/describe"
9
+ require_relative "objects/value"
10
+ require_relative "objects/list"
11
+ require_relative "objects/each_loop"
12
+ require_relative "objects/or_test"
13
+ require_relative "objects/test"
14
+ require_relative "objects/input"
15
+ require_relative "objects/post_body"
16
+ require_relative "objects/header"
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InspecObjects
4
+ VERSION = "0.3.2"
5
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mitre-inspec-objects/version"
4
+ require_relative "inspec/objects"
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "mitre-inspec-objects/version"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "mitre-inspec-objects"
10
+ spec.version = InspecObjects::VERSION
11
+ spec.authors = ["Dominik Richter", "Christoph Hartmann", "Aaron Lippold"]
12
+ spec.email = ["dominik.richter@gmail.com", "chris@lollyrock.com"]
13
+ spec.summary = "InSpec Objects library"
14
+ spec.description = "Library that provides an API for programmatically creating InSpec profiles"
15
+ spec.homepage = "https://github.com/mitre/inspec-objects"
16
+ spec.license = "Apache-2.0"
17
+
18
+ spec.files = %w{
19
+ README.md mitre-inspec-objects.gemspec Gemfile
20
+ } + Dir.glob("{lib}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
21
+
22
+ spec.require_paths = ["lib"]
23
+ spec.add_dependency "inspec-core"
24
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mitre-inspec-objects
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.2
5
+ platform: ruby
6
+ authors:
7
+ - Dominik Richter
8
+ - Christoph Hartmann
9
+ - Aaron Lippold
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2022-02-08 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: inspec-core
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ description: Library that provides an API for programmatically creating InSpec profiles
30
+ email:
31
+ - dominik.richter@gmail.com
32
+ - chris@lollyrock.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - Gemfile
38
+ - README.md
39
+ - lib/inspec/objects.rb
40
+ - lib/inspec/objects/control.rb
41
+ - lib/inspec/objects/describe.rb
42
+ - lib/inspec/objects/each_loop.rb
43
+ - lib/inspec/objects/header.rb
44
+ - lib/inspec/objects/input.rb
45
+ - lib/inspec/objects/list.rb
46
+ - lib/inspec/objects/or_test.rb
47
+ - lib/inspec/objects/post_body.rb
48
+ - lib/inspec/objects/ruby_helper.rb
49
+ - lib/inspec/objects/tag.rb
50
+ - lib/inspec/objects/test.rb
51
+ - lib/inspec/objects/value.rb
52
+ - lib/mitre-inspec-objects.rb
53
+ - lib/mitre-inspec-objects/version.rb
54
+ - mitre-inspec-objects.gemspec
55
+ homepage: https://github.com/mitre/inspec-objects
56
+ licenses:
57
+ - Apache-2.0
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.2.32
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: InSpec Objects library
78
+ test_files: []