inspec 1.17.0 → 1.18.0
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 +4 -4
- data/CHANGELOG.md +43 -2
- data/Gemfile +1 -0
- data/Rakefile +17 -1
- data/docs/habitat.md +192 -0
- data/docs/resources/gem.md.erb +20 -1
- data/docs/resources/key_rsa.md +70 -0
- data/docs/resources/x509_certificate.md +146 -0
- data/docs/resources/yum.md.erb +8 -0
- data/inspec.gemspec +3 -0
- data/lib/bundles/inspec-habitat/cli.rb +0 -1
- data/lib/bundles/inspec-habitat/profile.rb +23 -1
- data/lib/bundles/inspec-supermarket/api.rb +6 -4
- data/lib/fetchers/git.rb +3 -1
- data/lib/fetchers/url.rb +1 -0
- data/lib/inspec/base_cli.rb +6 -19
- data/lib/inspec/cli.rb +9 -0
- data/lib/inspec/objects.rb +1 -0
- data/lib/inspec/objects/control.rb +8 -2
- data/lib/inspec/objects/tag.rb +27 -0
- data/lib/inspec/profile_vendor.rb +66 -0
- data/lib/inspec/resource.rb +2 -0
- data/lib/inspec/schema.rb +174 -0
- data/lib/inspec/secrets/yaml.rb +3 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/gem.rb +20 -3
- data/lib/resources/key_rsa.rb +67 -0
- data/lib/resources/port.rb +26 -7
- data/lib/resources/x509_certificate.rb +143 -0
- data/lib/resources/yum.rb +22 -8
- data/lib/utils/simpleconfig.rb +7 -1
- metadata +26 -3
data/docs/resources/yum.md.erb
CHANGED
@@ -101,3 +101,11 @@ The following examples show how to use this InSpec audit resource.
|
|
101
101
|
it { should exist }
|
102
102
|
it { should be_enabled }
|
103
103
|
end
|
104
|
+
|
105
|
+
### Test a particular repository configuration, such as its Base URL
|
106
|
+
|
107
|
+
describe yum.repo('mycompany-artifacts') do
|
108
|
+
it { should exist }
|
109
|
+
it { should be_enabled }
|
110
|
+
its('baseurl') { should include 'mycompany.biz' }
|
111
|
+
end
|
data/inspec.gemspec
CHANGED
@@ -24,6 +24,8 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
25
25
|
spec.require_paths = ['lib']
|
26
26
|
|
27
|
+
spec.required_ruby_version = '>= 2.1'
|
28
|
+
|
27
29
|
spec.add_dependency 'train', '>=0.22.0', '<1.0'
|
28
30
|
spec.add_dependency 'thor', '~> 0.19'
|
29
31
|
spec.add_dependency 'json', '>= 1.8', '< 3.0'
|
@@ -40,4 +42,5 @@ Gem::Specification.new do |spec|
|
|
40
42
|
spec.add_dependency 'nokogiri', '~> 1.6'
|
41
43
|
spec.add_dependency 'faraday', '>=0.9.0'
|
42
44
|
spec.add_dependency 'toml', '~> 0.1'
|
45
|
+
spec.add_dependency 'addressable', '~> 2.5'
|
43
46
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# author: Adam Leff
|
3
3
|
|
4
|
+
require 'inspec/profile_vendor'
|
4
5
|
require 'mixlib/shellout'
|
5
6
|
require 'toml'
|
6
7
|
|
@@ -37,6 +38,8 @@ module Habitat
|
|
37
38
|
validate_habitat_installed
|
38
39
|
validate_habitat_origin
|
39
40
|
create_profile_object
|
41
|
+
verify_profile
|
42
|
+
vendor_profile_dependencies
|
40
43
|
copy_profile_to_work_dir
|
41
44
|
create_plan
|
42
45
|
create_run_hook
|
@@ -79,7 +82,10 @@ module Habitat
|
|
79
82
|
private
|
80
83
|
|
81
84
|
def create_profile_object
|
82
|
-
@profile = Inspec::Profile.for_target(
|
85
|
+
@profile = Inspec::Profile.for_target(
|
86
|
+
path,
|
87
|
+
backend: Inspec::Backend.create(target: 'mock://'),
|
88
|
+
)
|
83
89
|
end
|
84
90
|
|
85
91
|
def verify_profile
|
@@ -92,6 +98,22 @@ module Habitat
|
|
92
98
|
Habitat::Log.info('Profile is valid.')
|
93
99
|
end
|
94
100
|
|
101
|
+
def vendor_profile_dependencies
|
102
|
+
profile_vendor = Inspec::ProfileVendor.new(path)
|
103
|
+
if profile_vendor.lockfile.exist? && profile_vendor.cache_path.exist?
|
104
|
+
Habitat::Log.info("Profile's dependencies are already vendored, skipping vendor process.")
|
105
|
+
else
|
106
|
+
Habitat::Log.info("Vendoring the profile's dependencies...")
|
107
|
+
profile_vendor.vendor!
|
108
|
+
|
109
|
+
Habitat::Log.info('Ensuring all vendored content has read permissions...')
|
110
|
+
profile_vendor.make_readable
|
111
|
+
|
112
|
+
# refresh the profile object since the profile now has new files
|
113
|
+
create_profile_object
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
95
117
|
def validate_habitat_installed
|
96
118
|
Habitat::Log.info('Checking to see if Habitat is installed...')
|
97
119
|
cmd = Mixlib::ShellOut.new('hab --version')
|
@@ -4,6 +4,7 @@
|
|
4
4
|
# author: Dominik Richter
|
5
5
|
|
6
6
|
require 'net/http'
|
7
|
+
require 'addressable/uri'
|
7
8
|
|
8
9
|
module Supermarket
|
9
10
|
class API
|
@@ -26,9 +27,10 @@ module Supermarket
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def self.profile_name(profile)
|
29
|
-
|
30
|
+
# We use Addressable::URI here because URI has a bug in Ruby 2.1.x where it doesn't allow underscore in host
|
31
|
+
uri = Addressable::URI.parse profile
|
30
32
|
[uri.host, uri.path[1..-1]]
|
31
|
-
rescue
|
33
|
+
rescue
|
32
34
|
nil
|
33
35
|
end
|
34
36
|
|
@@ -50,8 +52,8 @@ module Supermarket
|
|
50
52
|
supermarket_tool['tool_owner'] == tool_owner && supermarket_tool['tool'] == tool
|
51
53
|
end
|
52
54
|
|
53
|
-
def self.find(profile, supermarket_url)
|
54
|
-
profiles = Supermarket::API.profiles(supermarket_url
|
55
|
+
def self.find(profile, supermarket_url = SUPERMARKET_URL)
|
56
|
+
profiles = Supermarket::API.profiles(supermarket_url)
|
55
57
|
if !profiles.empty?
|
56
58
|
index = profiles.index { |t| same?(profile, t, supermarket_url) }
|
57
59
|
# return profile or nil
|
data/lib/fetchers/git.rb
CHANGED
@@ -24,7 +24,7 @@ module Fetchers
|
|
24
24
|
# you got to this file during debugging, you may want to look at the
|
25
25
|
# omnibus source for hints.
|
26
26
|
#
|
27
|
-
class Git < Inspec.fetcher(1)
|
27
|
+
class Git < Inspec.fetcher(1) # rubocop:disable ClassLength
|
28
28
|
name 'git'
|
29
29
|
priority 200
|
30
30
|
|
@@ -44,6 +44,8 @@ module Fetchers
|
|
44
44
|
|
45
45
|
def fetch(dir)
|
46
46
|
@repo_directory = dir
|
47
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
48
|
+
|
47
49
|
if cloned?
|
48
50
|
checkout
|
49
51
|
else
|
data/lib/fetchers/url.rb
CHANGED
@@ -153,6 +153,7 @@ module Fetchers
|
|
153
153
|
def download_archive(path)
|
154
154
|
download_archive_to_temp
|
155
155
|
final_path = "#{path}#{@archive_type}"
|
156
|
+
FileUtils.mkdir_p(File.dirname(final_path))
|
156
157
|
FileUtils.mv(temp_archive_path, final_path)
|
157
158
|
Inspec::Log.debug("Fetched archive moved to: #{final_path}")
|
158
159
|
@temp_archive_path = nil
|
data/lib/inspec/base_cli.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
require 'thor'
|
6
6
|
require 'inspec/log'
|
7
|
+
require 'inspec/profile_vendor'
|
7
8
|
|
8
9
|
module Inspec
|
9
10
|
class BaseCLI < Thor # rubocop:disable Metrics/ClassLength
|
@@ -147,30 +148,16 @@ module Inspec
|
|
147
148
|
end
|
148
149
|
|
149
150
|
def vendor_deps(path, opts)
|
150
|
-
|
151
|
-
|
152
|
-
inspec_lock = path.join('inspec.lock')
|
151
|
+
profile_path = path || Dir.pwd
|
152
|
+
profile_vendor = Inspec::ProfileVendor.new(profile_path)
|
153
153
|
|
154
|
-
if (cache_path.exist? ||
|
154
|
+
if (profile_vendor.cache_path.exist? || profile_vendor.lockfile.exist?) && !opts[:overwrite]
|
155
155
|
puts 'Profile is already vendored. Use --overwrite.'
|
156
156
|
return false
|
157
157
|
end
|
158
158
|
|
159
|
-
|
160
|
-
|
161
|
-
File.delete(inspec_lock) if inspec_lock.exist?
|
162
|
-
|
163
|
-
puts "Vendor dependencies of #{path} into #{cache_path}"
|
164
|
-
opts[:logger] = Logger.new(STDOUT)
|
165
|
-
opts[:logger].level = get_log_level(opts.log_level)
|
166
|
-
opts[:cache] = Inspec::Cache.new(cache_path.to_s)
|
167
|
-
opts[:backend] = Inspec::Backend.create(target: 'mock://')
|
168
|
-
configure_logger(opts)
|
169
|
-
|
170
|
-
# vendor dependencies and generate lockfile
|
171
|
-
profile = Inspec::Profile.for_target(path.to_s, opts)
|
172
|
-
lockfile = profile.generate_lockfile
|
173
|
-
File.write(inspec_lock, lockfile.to_yaml)
|
159
|
+
profile_vendor.vendor!
|
160
|
+
puts "Dependencies for profile #{profile_path} successfully vendored to #{profile_vendor.cache_path}"
|
174
161
|
rescue StandardError => e
|
175
162
|
pretty_handle_exception(e)
|
176
163
|
end
|
data/lib/inspec/cli.rb
CHANGED
@@ -14,6 +14,7 @@ require 'inspec/base_cli'
|
|
14
14
|
require 'inspec/plugins'
|
15
15
|
require 'inspec/runner_mock'
|
16
16
|
require 'inspec/env_printer'
|
17
|
+
require 'inspec/schema'
|
17
18
|
|
18
19
|
class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
19
20
|
class_option :log_level, aliases: :l, type: :string,
|
@@ -221,6 +222,14 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
221
222
|
pretty_handle_exception(e)
|
222
223
|
end
|
223
224
|
|
225
|
+
desc 'schema NAME', 'print the JSON schema', hide: true
|
226
|
+
def schema(name)
|
227
|
+
puts Inspec::Schema.json(name)
|
228
|
+
rescue StandardError => e
|
229
|
+
puts e
|
230
|
+
puts "Valid schemas are #{Inspec::Schema.names.join(', ')}"
|
231
|
+
end
|
232
|
+
|
224
233
|
desc 'version', 'prints the version of this tool'
|
225
234
|
def version
|
226
235
|
puts Inspec::VERSION
|
data/lib/inspec/objects.rb
CHANGED
@@ -2,17 +2,22 @@
|
|
2
2
|
|
3
3
|
module Inspec
|
4
4
|
class Control
|
5
|
-
attr_accessor :id, :title, :desc, :impact, :tests
|
5
|
+
attr_accessor :id, :title, :desc, :impact, :tests, :tags
|
6
6
|
def initialize
|
7
7
|
@tests = []
|
8
|
+
@tags = []
|
8
9
|
end
|
9
10
|
|
10
11
|
def add_test(t)
|
11
12
|
@tests.push(t)
|
12
13
|
end
|
13
14
|
|
15
|
+
def add_tag(t)
|
16
|
+
@tags.push(t)
|
17
|
+
end
|
18
|
+
|
14
19
|
def to_hash
|
15
|
-
{ id: id, title: title, desc: desc, impact: impact, tests: tests.map(&:to_hash) }
|
20
|
+
{ id: id, title: title, desc: desc, impact: impact, tests: tests.map(&:to_hash), tags: tags.map(&:to_hash) }
|
16
21
|
end
|
17
22
|
|
18
23
|
def to_ruby
|
@@ -20,6 +25,7 @@ module Inspec
|
|
20
25
|
res.push " title #{title.inspect}" unless title.to_s.empty?
|
21
26
|
res.push " desc #{desc.inspect}" unless desc.to_s.empty?
|
22
27
|
res.push " impact #{impact}" unless impact.nil?
|
28
|
+
tags.each { |t| res.push(indent(t.to_ruby, 2)) }
|
23
29
|
tests.each { |t| res.push(indent(t.to_ruby, 2)) }
|
24
30
|
res.push 'end'
|
25
31
|
res.join("\n")
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
|
3
|
+
module Inspec
|
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.inspect}: #{value.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"Tag #{key} with #{value}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Adam Leff
|
3
|
+
|
4
|
+
require 'inspec/profile'
|
5
|
+
|
6
|
+
module Inspec
|
7
|
+
class ProfileVendor
|
8
|
+
attr_reader :profile_path
|
9
|
+
|
10
|
+
def initialize(path)
|
11
|
+
@profile_path = Pathname.new(path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def vendor!
|
15
|
+
vendor_dependencies
|
16
|
+
end
|
17
|
+
|
18
|
+
# The URL fetcher uses a Tempfile to retrieve the vendored
|
19
|
+
# profile, which creates a file that is only readable by
|
20
|
+
# the current user. In most circumstances, this is likely OK.
|
21
|
+
# However, in environments like a Habitat package, these files
|
22
|
+
# need to be readable by all users or the Habitat Supervisor
|
23
|
+
# may not be able to start InSpec correctly.
|
24
|
+
#
|
25
|
+
# This method makes sure all vendored files are mode 644 for this
|
26
|
+
# use case. This method is not called by default - the caller
|
27
|
+
# vendoring the profile must make the decision as to whether this
|
28
|
+
# is necessary.
|
29
|
+
def make_readable
|
30
|
+
Dir.glob("#{cache_path}/**/*") do |e|
|
31
|
+
FileUtils.chmod(0644, e) if File.file?(e)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def cache_path
|
36
|
+
profile_path.join('vendor')
|
37
|
+
end
|
38
|
+
|
39
|
+
def lockfile
|
40
|
+
profile_path.join('inspec.lock')
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def profile
|
46
|
+
@profile ||= Inspec::Profile.for_target(profile_path.to_s, profile_opts)
|
47
|
+
end
|
48
|
+
|
49
|
+
def profile_opts
|
50
|
+
{
|
51
|
+
cache: Inspec::Cache.new(cache_path.to_s),
|
52
|
+
backend: Inspec::Backend.create(target: 'mock://'),
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def vendor_dependencies
|
57
|
+
delete_vendored_data
|
58
|
+
File.write(lockfile, profile.generate_lockfile.to_yaml)
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete_vendored_data
|
62
|
+
FileUtils.rm_rf(cache_path) if cache_path.exist?
|
63
|
+
File.delete(lockfile) if lockfile.exist?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/inspec/resource.rb
CHANGED
@@ -95,6 +95,7 @@ require 'resources/iptables'
|
|
95
95
|
require 'resources/json'
|
96
96
|
require 'resources/kernel_module'
|
97
97
|
require 'resources/kernel_parameter'
|
98
|
+
require 'resources/key_rsa'
|
98
99
|
require 'resources/limits_conf'
|
99
100
|
require 'resources/login_def'
|
100
101
|
require 'resources/mount'
|
@@ -131,6 +132,7 @@ require 'resources/windows_feature'
|
|
131
132
|
require 'resources/windows_task'
|
132
133
|
require 'resources/xinetd'
|
133
134
|
require 'resources/wmi'
|
135
|
+
require 'resources/x509_certificate'
|
134
136
|
require 'resources/yum'
|
135
137
|
require 'resources/zfs_dataset'
|
136
138
|
require 'resources/zfs_pool'
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Inspec
|
5
|
+
class Schema # rubocop:disable Metrics/ClassLength
|
6
|
+
STATISTICS = {
|
7
|
+
'type' => 'object',
|
8
|
+
'additionalProperties' => false,
|
9
|
+
'properties' => {
|
10
|
+
'duration' => { 'type' => 'number' },
|
11
|
+
},
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
# Tags are open right, with simple key-value associations and not restrictions
|
15
|
+
TAGS = { 'type' => 'object' }.freeze
|
16
|
+
|
17
|
+
RESULT = {
|
18
|
+
'type' => 'object',
|
19
|
+
'additionalProperties' => false,
|
20
|
+
'properties' => {
|
21
|
+
'status' => { 'type' => 'string' },
|
22
|
+
'code_desc' => { 'type' => 'string' },
|
23
|
+
'run_time' => { 'type' => 'number' },
|
24
|
+
'start_time' => { 'type' => 'string' },
|
25
|
+
'skip_message' => { 'type' => 'string', 'optional' => true },
|
26
|
+
'resource' => { 'type' => 'string', 'optional' => true },
|
27
|
+
},
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
REF = {
|
31
|
+
'type' => 'object',
|
32
|
+
'additionalProperties' => false,
|
33
|
+
'properties' => {
|
34
|
+
'ref' => { 'type' => 'string' },
|
35
|
+
# TODO: One of these needs to be deprecated
|
36
|
+
'uri' => { 'type' => 'string', 'optional' => true },
|
37
|
+
'url' => { 'type' => 'string', 'optional' => true },
|
38
|
+
},
|
39
|
+
}.freeze
|
40
|
+
REFS = { 'type' => 'array', 'items' => REF }.freeze
|
41
|
+
|
42
|
+
CONTROL = {
|
43
|
+
'type' => 'object',
|
44
|
+
'additionalProperties' => false,
|
45
|
+
'properties' => {
|
46
|
+
'id' => { 'type' => 'string' },
|
47
|
+
'title' => { 'type' => %w{string null} },
|
48
|
+
'desc' => { 'type' => %w{string null} },
|
49
|
+
'impact' => { 'type' => 'number' },
|
50
|
+
'refs' => REFS,
|
51
|
+
'tags' => TAGS,
|
52
|
+
'code' => { 'type' => 'string' },
|
53
|
+
'source_location' => {
|
54
|
+
'type' => 'object',
|
55
|
+
'properties' => {
|
56
|
+
'ref' => { 'type' => 'string' },
|
57
|
+
'line' => { 'type' => 'number' },
|
58
|
+
},
|
59
|
+
},
|
60
|
+
'results' => { 'type' => 'array', 'items' => RESULT },
|
61
|
+
},
|
62
|
+
}.freeze
|
63
|
+
|
64
|
+
SUPPORTS = {
|
65
|
+
'type' => 'object',
|
66
|
+
'additionalProperties' => false,
|
67
|
+
'properties' => {
|
68
|
+
'os-family' => { 'type' => 'string', 'optional' => true },
|
69
|
+
},
|
70
|
+
}.freeze
|
71
|
+
|
72
|
+
CONTROL_GROUP = {
|
73
|
+
'type' => 'object',
|
74
|
+
'additionalProperties' => false,
|
75
|
+
'properties' => {
|
76
|
+
'id' => { 'type' => 'string' },
|
77
|
+
'title' => { 'type' => 'string', 'optional' => true },
|
78
|
+
'controls' => { 'type' => 'array', 'items' => { 'type' => 'string' } },
|
79
|
+
},
|
80
|
+
}.freeze
|
81
|
+
|
82
|
+
PROFILE = {
|
83
|
+
'type' => 'object',
|
84
|
+
'additionalProperties' => false,
|
85
|
+
'properties' => {
|
86
|
+
'name' => { 'type' => 'string' },
|
87
|
+
'version' => { 'type' => 'string', 'optional' => true },
|
88
|
+
|
89
|
+
'title' => { 'type' => 'string', 'optional' => true },
|
90
|
+
'maintainer' => { 'type' => 'string', 'optional' => true },
|
91
|
+
'copyright' => { 'type' => 'string', 'optional' => true },
|
92
|
+
'copyright_email' => { 'type' => 'string', 'optional' => true },
|
93
|
+
'license' => { 'type' => 'string', 'optional' => true },
|
94
|
+
'summary' => { 'type' => 'string', 'optional' => true },
|
95
|
+
|
96
|
+
'supports' => {
|
97
|
+
'type' => 'array',
|
98
|
+
'items' => SUPPORTS,
|
99
|
+
'optional' => true,
|
100
|
+
},
|
101
|
+
'controls' => {
|
102
|
+
'type' => 'array',
|
103
|
+
'items' => CONTROL,
|
104
|
+
},
|
105
|
+
'groups' => {
|
106
|
+
'type' => 'array',
|
107
|
+
'items' => CONTROL_GROUP,
|
108
|
+
},
|
109
|
+
'attributes' => {
|
110
|
+
'type' => 'array',
|
111
|
+
# TODO: more detailed specification needed
|
112
|
+
},
|
113
|
+
},
|
114
|
+
}.freeze
|
115
|
+
|
116
|
+
EXEC_JSON = {
|
117
|
+
'type' => 'object',
|
118
|
+
'additionalProperties' => false,
|
119
|
+
'properties' => {
|
120
|
+
'profiles' => {
|
121
|
+
'type' => 'array',
|
122
|
+
'items' => PROFILE,
|
123
|
+
},
|
124
|
+
'statistics' => STATISTICS,
|
125
|
+
'version' => { 'type' => 'string' },
|
126
|
+
|
127
|
+
# DEPRECATED PROPERTIES!! These will be removed with the next major version bump
|
128
|
+
'controls' => 'array',
|
129
|
+
'other_checks' => 'array',
|
130
|
+
},
|
131
|
+
}.freeze
|
132
|
+
|
133
|
+
MIN_CONTROL = {
|
134
|
+
'type' => 'object',
|
135
|
+
'additionalProperties' => false,
|
136
|
+
'properties' => {
|
137
|
+
'id' => { 'type' => 'string' },
|
138
|
+
'profile_id' => { 'type' => %w{string null} },
|
139
|
+
'status' => { 'type' => 'string' },
|
140
|
+
'code_desc' => { 'type' => 'string' },
|
141
|
+
'skip_message' => { 'type' => 'string', 'optional' => true },
|
142
|
+
'resource' => { 'type' => 'string', 'optional' => true },
|
143
|
+
},
|
144
|
+
}.freeze
|
145
|
+
|
146
|
+
EXEC_JSONMIN = {
|
147
|
+
'type' => 'object',
|
148
|
+
'additionalProperties' => false,
|
149
|
+
'properties' => {
|
150
|
+
'statistics' => STATISTICS,
|
151
|
+
'version' => { 'type' => 'string' },
|
152
|
+
'controls' => {
|
153
|
+
'type' => 'array',
|
154
|
+
'items' => MIN_CONTROL,
|
155
|
+
},
|
156
|
+
},
|
157
|
+
}.freeze
|
158
|
+
|
159
|
+
LIST = {
|
160
|
+
'exec-json' => EXEC_JSON,
|
161
|
+
'exec-jsonmin' => EXEC_JSONMIN,
|
162
|
+
}.freeze
|
163
|
+
|
164
|
+
def self.names
|
165
|
+
LIST.keys
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.json(name)
|
169
|
+
v = LIST[name] ||
|
170
|
+
raise("Cannot find schema #{name.inspect}.")
|
171
|
+
JSON.dump(v)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|