inspec 1.0.0 → 1.35.1
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 +933 -101
- data/Gemfile +8 -17
- data/MAINTAINERS.md +2 -1
- data/MAINTAINERS.toml +9 -4
- data/README.md +49 -28
- data/Rakefile +54 -39
- data/bin/inspec +1 -1
- data/docs/dsl_inspec.md +17 -4
- data/docs/dsl_resource.md +1 -1
- data/docs/habitat.md +192 -0
- data/docs/inspec_and_friends.md +4 -2
- data/docs/matchers.md +11 -0
- data/docs/migration.md +293 -0
- data/docs/profiles.md +124 -76
- data/docs/resources/aide_conf.md.erb +81 -0
- data/docs/resources/apache_conf.md.erb +10 -10
- data/docs/resources/apt.md.erb +13 -13
- data/docs/resources/audit_policy.md.erb +10 -10
- data/docs/resources/auditd_conf.md.erb +10 -10
- data/docs/resources/auditd_rules.md.erb +11 -11
- data/docs/resources/bash.md.erb +12 -12
- data/docs/resources/bond.md.erb +15 -15
- data/docs/resources/bridge.md.erb +11 -11
- data/docs/resources/bsd_service.md.erb +11 -11
- data/docs/resources/command.md.erb +23 -23
- data/docs/resources/crontab.md.erb +84 -0
- data/docs/resources/csv.md.erb +10 -10
- data/docs/resources/dh_params.md +191 -0
- data/docs/resources/directory.md.erb +8 -8
- data/docs/resources/docker.md.erb +160 -0
- data/docs/resources/docker_container.md.erb +89 -0
- data/docs/resources/docker_image.md.erb +86 -0
- data/docs/resources/etc_group.md.erb +16 -16
- data/docs/resources/etc_hosts.md.erb +62 -0
- data/docs/resources/file.md.erb +80 -58
- data/docs/resources/gem.md.erb +32 -13
- data/docs/resources/group.md.erb +12 -12
- data/docs/resources/grub_conf.md.erb +11 -11
- data/docs/resources/host.md.erb +27 -18
- data/docs/resources/http.md.erb +104 -0
- data/docs/resources/iis_app.md.erb +126 -0
- data/docs/resources/iis_site.md.erb +17 -17
- data/docs/resources/inetd_conf.md.erb +10 -10
- data/docs/resources/ini.md.erb +9 -9
- data/docs/resources/interface.md.erb +13 -13
- data/docs/resources/iptables.md.erb +21 -14
- data/docs/resources/json.md.erb +11 -11
- data/docs/resources/kernel_module.md.erb +73 -12
- data/docs/resources/kernel_parameter.md.erb +12 -12
- data/docs/resources/key_rsa.md.erb +70 -0
- data/docs/resources/launchd_service.md.erb +11 -11
- data/docs/resources/limits_conf.md.erb +10 -10
- data/docs/resources/login_def.md.erb +12 -12
- data/docs/resources/mount.md.erb +14 -14
- data/docs/resources/mssql_session.md.erb +62 -0
- data/docs/resources/mysql_conf.md.erb +14 -14
- data/docs/resources/mysql_session.md.erb +22 -10
- data/docs/resources/npm.md.erb +13 -13
- data/docs/resources/ntp_conf.md.erb +9 -9
- data/docs/resources/oneget.md.erb +11 -11
- data/docs/resources/oracledb_session.md.erb +53 -0
- data/docs/resources/os.md.erb +17 -17
- data/docs/resources/os_env.md.erb +12 -12
- data/docs/resources/package.md.erb +29 -16
- data/docs/resources/parse_config.md.erb +18 -18
- data/docs/resources/parse_config_file.md.erb +29 -23
- data/docs/resources/{etc_passwd.md.erb → passwd.md.erb} +17 -17
- data/docs/resources/pip.md.erb +15 -15
- data/docs/resources/port.md.erb +23 -23
- data/docs/resources/postgres_conf.md.erb +15 -13
- data/docs/resources/postgres_hba_conf.md.erb +104 -0
- data/docs/resources/postgres_ident_conf.md.erb +87 -0
- data/docs/resources/postgres_session.md.erb +28 -21
- data/docs/resources/powershell.md.erb +14 -14
- data/docs/resources/processes.md.erb +123 -0
- data/docs/resources/rabbitmq_config.md.erb +55 -0
- data/docs/resources/registry_key.md.erb +44 -21
- data/docs/resources/runit_service.md.erb +11 -11
- data/docs/resources/security_policy.md.erb +10 -10
- data/docs/resources/service.md.erb +18 -18
- data/docs/resources/{etc_shadow.md.erb → shadow.md.erb} +19 -19
- data/docs/resources/ssh_config.md.erb +13 -13
- data/docs/resources/sshd_config.md.erb +15 -15
- data/docs/resources/ssl.md.erb +13 -13
- data/docs/resources/sys_info.md.erb +10 -10
- data/docs/resources/systemd_service.md.erb +11 -11
- data/docs/resources/sysv_service.md.erb +11 -11
- data/docs/resources/upstart_service.md.erb +11 -11
- data/docs/resources/user.md.erb +20 -20
- data/docs/resources/users.md.erb +19 -19
- data/docs/resources/vbscript.md.erb +13 -13
- data/docs/resources/virtualization.md.erb +71 -0
- data/docs/resources/windows_feature.md.erb +10 -10
- data/docs/resources/windows_task.md.erb +103 -0
- data/docs/resources/wmi.md.erb +10 -10
- data/docs/resources/x509_certificate.md.erb +146 -0
- data/docs/resources/xinetd_conf.md.erb +17 -17
- data/docs/resources/xml.md.erb +75 -0
- data/docs/resources/yaml.md.erb +25 -11
- data/docs/resources/yum.md.erb +24 -16
- data/docs/resources/zfs_dataset.md.erb +63 -0
- data/docs/resources/zfs_pool.md.erb +57 -0
- data/docs/ruby_usage.md +50 -0
- data/docs/shared/matcher_cmp.md.erb +4 -6
- data/examples/inheritance/README.md +49 -3
- data/examples/inheritance/controls/example.rb +4 -1
- data/examples/inheritance/inspec.yml +3 -1
- data/examples/meta-profile/README.md +29 -3
- data/examples/meta-profile/controls/example.rb +10 -5
- data/examples/meta-profile/inspec.yml +4 -8
- data/examples/profile/README.md +1 -1
- data/examples/profile/controls/example.rb +0 -1
- data/examples/profile/controls/gordon.rb +0 -1
- data/examples/profile/inspec.yml +1 -1
- data/examples/profile-attribute/inspec.yml +1 -1
- data/examples/profile-sensitive/README.md +29 -0
- data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -0
- data/examples/profile-sensitive/controls/sensitive.rb +9 -0
- data/examples/profile-sensitive/inspec.yml +8 -0
- data/inspec.gemspec +10 -2
- data/lib/bundles/inspec-artifact/README.md +1 -0
- data/lib/bundles/inspec-artifact/cli.rb +284 -0
- data/lib/bundles/inspec-artifact.rb +7 -0
- data/lib/bundles/inspec-compliance/README.md +44 -15
- data/lib/bundles/inspec-compliance/api.rb +135 -29
- data/lib/bundles/inspec-compliance/cli.rb +128 -21
- data/lib/bundles/inspec-compliance/configuration.rb +8 -0
- data/lib/bundles/inspec-compliance/http.rb +26 -19
- data/lib/bundles/inspec-compliance/target.rb +50 -25
- data/lib/bundles/inspec-habitat/cli.rb +31 -0
- data/lib/bundles/inspec-habitat/log.rb +10 -0
- data/lib/bundles/inspec-habitat/profile.rb +372 -0
- data/lib/bundles/inspec-habitat.rb +12 -0
- data/lib/bundles/inspec-init/templates/profile/controls/example.rb +0 -1
- data/lib/bundles/inspec-init/templates/profile/inspec.yml +1 -1
- data/lib/bundles/inspec-supermarket/api.rb +7 -5
- data/lib/bundles/inspec-supermarket/cli.rb +2 -2
- data/lib/fetchers/git.rb +4 -2
- data/lib/fetchers/local.rb +4 -1
- data/lib/fetchers/url.rb +64 -10
- data/lib/inspec/archive/tar.rb +1 -1
- data/lib/inspec/backend.rb +26 -3
- data/lib/inspec/base_cli.rb +44 -7
- data/lib/inspec/cached_fetcher.rb +2 -2
- data/lib/inspec/cli.rb +34 -12
- data/lib/inspec/completions/fish.sh.erb +34 -0
- data/lib/inspec/control_eval_context.rb +0 -2
- data/lib/inspec/dependencies/cache.rb +0 -1
- data/lib/inspec/dependencies/dependency_set.rb +2 -2
- data/lib/inspec/dependencies/lockfile.rb +13 -6
- data/lib/inspec/dependencies/requirement.rb +6 -6
- data/lib/inspec/dependencies/resolver.rb +4 -4
- data/lib/inspec/dsl.rb +3 -5
- data/lib/inspec/env_printer.rb +9 -1
- data/lib/inspec/exceptions.rb +8 -0
- data/lib/inspec/fetcher.rb +1 -1
- data/lib/inspec/file_provider.rb +47 -11
- data/lib/inspec/library_eval_context.rb +1 -1
- data/lib/inspec/metadata.rb +62 -18
- data/lib/inspec/method_source.rb +24 -0
- data/lib/inspec/objects/attribute.rb +21 -0
- data/lib/inspec/objects/control.rb +21 -3
- data/lib/inspec/objects/each_loop.rb +2 -1
- data/lib/inspec/objects/list.rb +1 -1
- data/lib/inspec/objects/or_test.rb +17 -2
- data/lib/inspec/objects/tag.rb +27 -0
- data/lib/inspec/objects/test.rb +9 -8
- data/lib/inspec/objects.rb +1 -0
- data/lib/inspec/plugins/fetcher.rb +4 -5
- data/lib/inspec/plugins/resource.rb +1 -2
- data/lib/inspec/plugins/source_reader.rb +3 -3
- data/lib/inspec/plugins.rb +1 -1
- data/lib/inspec/polyfill.rb +0 -1
- data/lib/inspec/profile.rb +92 -23
- data/lib/inspec/profile_context.rb +1 -1
- data/lib/inspec/profile_vendor.rb +66 -0
- data/lib/inspec/resource.rb +29 -3
- data/lib/inspec/rspec_json_formatter.rb +672 -285
- data/lib/inspec/rule.rb +12 -16
- data/lib/inspec/runner.rb +26 -15
- data/lib/inspec/runner_rspec.rb +1 -0
- data/lib/inspec/runtime_profile.rb +26 -0
- data/lib/inspec/schema.rb +185 -0
- data/lib/inspec/secrets/yaml.rb +8 -1
- data/lib/inspec/secrets.rb +1 -1
- data/lib/inspec/shell.rb +92 -22
- data/lib/inspec/source_reader.rb +1 -1
- data/lib/inspec/version.rb +1 -1
- data/lib/inspec.rb +1 -1
- data/lib/matchers/matchers.rb +67 -17
- data/lib/resources/aide_conf.rb +162 -0
- data/lib/resources/apache.rb +0 -1
- data/lib/resources/apache_conf.rb +3 -3
- data/lib/resources/apt.rb +2 -1
- data/lib/resources/audit_policy.rb +0 -1
- data/lib/resources/auditd_conf.rb +1 -2
- data/lib/resources/auditd_rules.rb +5 -5
- data/lib/resources/bond.rb +1 -1
- data/lib/resources/bridge.rb +1 -1
- data/lib/resources/command.rb +5 -3
- data/lib/resources/crontab.rb +102 -0
- data/lib/resources/csv.rb +18 -1
- data/lib/resources/dh_params.rb +84 -0
- data/lib/resources/directory.rb +7 -3
- data/lib/resources/docker.rb +198 -0
- data/lib/resources/docker_container.rb +114 -0
- data/lib/resources/docker_image.rb +96 -0
- data/lib/resources/etc_group.rb +2 -3
- data/lib/resources/etc_hosts.rb +81 -0
- data/lib/resources/file.rb +88 -30
- data/lib/resources/gem.rb +26 -6
- data/lib/resources/groups.rb +4 -5
- data/lib/resources/grub_conf.rb +3 -4
- data/lib/resources/host.rb +175 -35
- data/lib/resources/http.rb +73 -0
- data/lib/resources/iis_app.rb +103 -0
- data/lib/resources/iis_site.rb +23 -0
- data/lib/resources/inetd_conf.rb +9 -4
- data/lib/resources/interface.rb +4 -3
- data/lib/resources/json.rb +37 -14
- data/lib/resources/kernel_module.rb +77 -10
- data/lib/resources/kernel_parameter.rb +0 -1
- data/lib/resources/key_rsa.rb +67 -0
- data/lib/resources/limits_conf.rb +3 -4
- data/lib/resources/login_def.rb +2 -3
- data/lib/resources/mount.rb +34 -4
- data/lib/resources/mssql_session.rb +81 -12
- data/lib/resources/mysql.rb +0 -1
- data/lib/resources/mysql_conf.rb +1 -2
- data/lib/resources/mysql_session.rb +18 -7
- data/lib/resources/nginx_conf.rb +95 -0
- data/lib/resources/ntp_conf.rb +2 -3
- data/lib/resources/oracledb_session.rb +138 -0
- data/lib/resources/os_env.rb +7 -5
- data/lib/resources/package.rb +70 -13
- data/lib/resources/packages.rb +111 -0
- data/lib/resources/parse_config.rb +3 -4
- data/lib/resources/passwd.rb +4 -5
- data/lib/resources/pip.rb +29 -21
- data/lib/resources/port.rb +133 -14
- data/lib/resources/postgres.rb +53 -43
- data/lib/resources/postgres_conf.rb +40 -13
- data/lib/resources/postgres_hba_conf.rb +101 -0
- data/lib/resources/postgres_ident_conf.rb +79 -0
- data/lib/resources/postgres_session.rb +28 -20
- data/lib/resources/powershell.rb +2 -2
- data/lib/resources/processes.rb +61 -26
- data/lib/resources/rabbitmq_conf.rb +53 -0
- data/lib/resources/registry_key.rb +34 -11
- data/lib/resources/security_policy.rb +2 -2
- data/lib/resources/service.rb +17 -7
- data/lib/resources/ssh_conf.rb +17 -6
- data/lib/resources/ssl.rb +3 -4
- data/lib/resources/sys_info.rb +1 -1
- data/lib/resources/toml.rb +26 -0
- data/lib/resources/users.rb +41 -41
- data/lib/resources/virtualization.rb +252 -0
- data/lib/resources/windows_task.rb +106 -0
- data/lib/resources/x509_certificate.rb +143 -0
- data/lib/resources/xinetd.rb +18 -2
- data/lib/resources/xml.rb +27 -0
- data/lib/resources/yaml.rb +10 -2
- data/lib/resources/yum.rb +25 -7
- data/lib/resources/zfs_dataset.rb +60 -0
- data/lib/resources/zfs_pool.rb +49 -0
- data/lib/source_readers/flat.rb +2 -1
- data/lib/source_readers/inspec.rb +30 -11
- data/lib/utils/command_wrapper.rb +3 -3
- data/lib/utils/database_helpers.rb +77 -0
- data/lib/utils/erlang_parser.rb +192 -0
- data/lib/utils/filter.rb +2 -1
- data/lib/utils/filter_array.rb +0 -1
- data/lib/utils/find_files.rb +1 -2
- data/lib/utils/latest_version.rb +21 -0
- data/lib/utils/nginx_parser.rb +76 -0
- data/lib/utils/object_traversal.rb +5 -4
- data/lib/utils/parser.rb +23 -4
- data/lib/utils/plugin_registry.rb +3 -3
- data/lib/utils/simpleconfig.rb +25 -8
- data/lib/utils/spdx.rb +13 -0
- data/lib/utils/spdx.txt +344 -0
- metadata +168 -22
- data/docs/cli.md +0 -342
- data/docs/resources/process.md.erb +0 -73
- /data/docs/{plugin_kitchen_inspec.html.md → plugin_kitchen_inspec.md} +0 -0
data/lib/inspec/rule.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# copyright: 2015, Dominik Richter
|
|
3
|
-
# license: All rights reserved
|
|
4
3
|
# author: Dominik Richter
|
|
5
4
|
# author: Christoph Hartmann
|
|
6
5
|
|
|
@@ -39,7 +38,6 @@ module Inspec
|
|
|
39
38
|
|
|
40
39
|
# not changeable by the user:
|
|
41
40
|
@__block = block
|
|
42
|
-
@__code = __get_block_source(&block)
|
|
43
41
|
@__source_location = __get_block_source_location(&block)
|
|
44
42
|
@__rule_id = id
|
|
45
43
|
@__profile_id = profile_id
|
|
@@ -231,24 +229,22 @@ module Inspec
|
|
|
231
229
|
end
|
|
232
230
|
end
|
|
233
231
|
|
|
234
|
-
# Idio(ma)tic unindent
|
|
235
|
-
#
|
|
232
|
+
# Idio(ma)tic unindent, behaves similar to Ruby2.3 curly heredocs.
|
|
233
|
+
# Find the shortest indentation of non-empty lines and strip that from every line
|
|
234
|
+
# See: https://bugs.ruby-lang.org/issues/9098
|
|
235
|
+
#
|
|
236
|
+
# It is implemented here to support pre-Ruby2.3 with this feature and
|
|
237
|
+
# to not force non-programmers to understand heredocs.
|
|
238
|
+
#
|
|
239
|
+
# Please note: tabs are not supported! (they will be removed but they are not
|
|
240
|
+
# treated the same as in Ruby2.3 heredocs)
|
|
236
241
|
#
|
|
237
242
|
# @param [String] text string which needs to be unindented
|
|
238
|
-
# @return [String] input with indentation removed
|
|
243
|
+
# @return [String] input with indentation removed; '' if input is nil
|
|
239
244
|
def unindent(text)
|
|
240
245
|
return '' if text.nil?
|
|
241
|
-
text.
|
|
242
|
-
|
|
243
|
-
.join(' ')
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
# get the rule's source code
|
|
247
|
-
def __get_block_source(&block)
|
|
248
|
-
return '' unless block_given?
|
|
249
|
-
block.source.to_s
|
|
250
|
-
rescue MethodSource::SourceNotFoundError
|
|
251
|
-
''
|
|
246
|
+
len = text.split("\n").reject { |l| l.strip.empty? }.map { |x| x.index(/[^\s]/) }.compact.min
|
|
247
|
+
text.gsub(/^[[:blank:]]{#{len}}/, '').strip
|
|
252
248
|
end
|
|
253
249
|
|
|
254
250
|
# get the source location of the block
|
data/lib/inspec/runner.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# copyright: 2015, Dominik Richter
|
|
3
|
-
# license: All rights reserved
|
|
4
3
|
# author: Dominik Richter
|
|
5
4
|
# author: Christoph Hartmann
|
|
6
5
|
|
|
@@ -80,7 +79,12 @@ module Inspec
|
|
|
80
79
|
@test_collector.add_profile(profile)
|
|
81
80
|
write_lockfile(profile) if @create_lockfile
|
|
82
81
|
profile.locked_dependencies
|
|
83
|
-
profile.load_libraries
|
|
82
|
+
profile_context = profile.load_libraries
|
|
83
|
+
|
|
84
|
+
profile_context.dependencies.list.values.each do |requirement|
|
|
85
|
+
@test_collector.add_profile(requirement.profile)
|
|
86
|
+
end
|
|
87
|
+
|
|
84
88
|
@attributes |= profile.runner_context.attributes
|
|
85
89
|
all_controls += profile.collect_tests
|
|
86
90
|
end
|
|
@@ -114,17 +118,24 @@ module Inspec
|
|
|
114
118
|
|
|
115
119
|
# determine all attributes before the execution, fetch data from secrets backend
|
|
116
120
|
def load_attributes(options)
|
|
117
|
-
attributes
|
|
118
|
-
|
|
119
|
-
secrets_targets = options[
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
options[:attributes] ||= {}
|
|
122
|
+
|
|
123
|
+
secrets_targets = options[:attrs]
|
|
124
|
+
return options[:attributes] if secrets_targets.nil?
|
|
125
|
+
|
|
126
|
+
secrets_targets.each do |target|
|
|
127
|
+
secrets = Inspec::SecretsBackend.resolve(target)
|
|
128
|
+
if secrets.nil?
|
|
129
|
+
raise Inspec::Exceptions::SecretsBackendNotFound,
|
|
130
|
+
"Unable to find a parser for attributes file #{target}. " \
|
|
131
|
+
'Check to make sure the file exists and has the appropriate extension.'
|
|
125
132
|
end
|
|
133
|
+
|
|
134
|
+
next if secrets.attributes.nil?
|
|
135
|
+
options[:attributes].merge!(secrets.attributes)
|
|
126
136
|
end
|
|
127
|
-
|
|
137
|
+
|
|
138
|
+
options[:attributes]
|
|
128
139
|
end
|
|
129
140
|
|
|
130
141
|
#
|
|
@@ -159,7 +170,7 @@ module Inspec
|
|
|
159
170
|
backend: @backend,
|
|
160
171
|
controls: @controls,
|
|
161
172
|
attributes: @conf[:attributes])
|
|
162
|
-
|
|
173
|
+
raise "Could not resolve #{target} to valid input." if profile.nil?
|
|
163
174
|
@target_profiles << profile if supports_profile?(profile)
|
|
164
175
|
end
|
|
165
176
|
|
|
@@ -167,13 +178,13 @@ module Inspec
|
|
|
167
178
|
return true if @ignore_supports
|
|
168
179
|
|
|
169
180
|
if !profile.supports_runtime?
|
|
170
|
-
|
|
181
|
+
raise 'This profile requires InSpec version '\
|
|
171
182
|
"#{profile.metadata.inspec_requirement}. You are running "\
|
|
172
183
|
"InSpec v#{Inspec::VERSION}.\n"
|
|
173
184
|
end
|
|
174
185
|
|
|
175
186
|
if !profile.supports_os?
|
|
176
|
-
|
|
187
|
+
raise "This OS/platform (#{@backend.os[:name]}) is not supported by this profile."
|
|
177
188
|
end
|
|
178
189
|
|
|
179
190
|
true
|
|
@@ -242,7 +253,7 @@ module Inspec
|
|
|
242
253
|
# otherwise return all working tests
|
|
243
254
|
return ok_tests
|
|
244
255
|
else
|
|
245
|
-
|
|
256
|
+
raise "A rule was registered with #{method_name.inspect}, "\
|
|
246
257
|
"which isn't understood and cannot be processed."
|
|
247
258
|
end
|
|
248
259
|
end
|
data/lib/inspec/runner_rspec.rb
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
# Copyright 2017 Chef Software
|
|
3
|
+
# author: Dominik Richter
|
|
4
|
+
# author: Christoph Hartmann
|
|
5
|
+
|
|
6
|
+
module Inspec
|
|
7
|
+
class RuntimeProfile
|
|
8
|
+
attr_reader :files
|
|
9
|
+
|
|
10
|
+
def initialize(profile)
|
|
11
|
+
@src = profile.source_reader
|
|
12
|
+
@files = @src.data_files.keys.map do |k|
|
|
13
|
+
k.sub('files' + File::SEPARATOR, '')
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Retrieve a profile file's contents
|
|
18
|
+
#
|
|
19
|
+
# @param name [String] the name of the file
|
|
20
|
+
# @return [String] contents of the file of RuntimeError if missing
|
|
21
|
+
def file(name)
|
|
22
|
+
@src.data_files[File.join('files', name)] ||
|
|
23
|
+
raise("Cannot find file #{name} in profile.")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
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
|
+
PLATFORM = {
|
|
15
|
+
'type' => 'object',
|
|
16
|
+
'additionalProperties' => false,
|
|
17
|
+
'properties' => {
|
|
18
|
+
'name' => { 'type' => 'string' },
|
|
19
|
+
'release' => { 'type' => 'string' },
|
|
20
|
+
},
|
|
21
|
+
}.freeze
|
|
22
|
+
|
|
23
|
+
# Tags are open right, with simple key-value associations and not restrictions
|
|
24
|
+
TAGS = { 'type' => 'object' }.freeze
|
|
25
|
+
|
|
26
|
+
RESULT = {
|
|
27
|
+
'type' => 'object',
|
|
28
|
+
'additionalProperties' => false,
|
|
29
|
+
'properties' => {
|
|
30
|
+
'status' => { 'type' => 'string' },
|
|
31
|
+
'code_desc' => { 'type' => 'string' },
|
|
32
|
+
'run_time' => { 'type' => 'number' },
|
|
33
|
+
'start_time' => { 'type' => 'string' },
|
|
34
|
+
'skip_message' => { 'type' => 'string', 'optional' => true },
|
|
35
|
+
'resource' => { 'type' => 'string', 'optional' => true },
|
|
36
|
+
},
|
|
37
|
+
}.freeze
|
|
38
|
+
|
|
39
|
+
REF = {
|
|
40
|
+
'type' => 'object',
|
|
41
|
+
'additionalProperties' => false,
|
|
42
|
+
'properties' => {
|
|
43
|
+
'ref' => { 'type' => 'string' },
|
|
44
|
+
# TODO: One of these needs to be deprecated
|
|
45
|
+
'uri' => { 'type' => 'string', 'optional' => true },
|
|
46
|
+
'url' => { 'type' => 'string', 'optional' => true },
|
|
47
|
+
},
|
|
48
|
+
}.freeze
|
|
49
|
+
REFS = { 'type' => 'array', 'items' => REF }.freeze
|
|
50
|
+
|
|
51
|
+
CONTROL = {
|
|
52
|
+
'type' => 'object',
|
|
53
|
+
'additionalProperties' => false,
|
|
54
|
+
'properties' => {
|
|
55
|
+
'id' => { 'type' => 'string' },
|
|
56
|
+
'title' => { 'type' => %w{string null} },
|
|
57
|
+
'desc' => { 'type' => %w{string null} },
|
|
58
|
+
'impact' => { 'type' => 'number' },
|
|
59
|
+
'refs' => REFS,
|
|
60
|
+
'tags' => TAGS,
|
|
61
|
+
'code' => { 'type' => 'string' },
|
|
62
|
+
'source_location' => {
|
|
63
|
+
'type' => 'object',
|
|
64
|
+
'properties' => {
|
|
65
|
+
'ref' => { 'type' => 'string' },
|
|
66
|
+
'line' => { 'type' => 'number' },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
'results' => { 'type' => 'array', 'items' => RESULT },
|
|
70
|
+
},
|
|
71
|
+
}.freeze
|
|
72
|
+
|
|
73
|
+
SUPPORTS = {
|
|
74
|
+
'type' => 'object',
|
|
75
|
+
'additionalProperties' => false,
|
|
76
|
+
'properties' => {
|
|
77
|
+
'os-family' => { 'type' => 'string', 'optional' => true },
|
|
78
|
+
},
|
|
79
|
+
}.freeze
|
|
80
|
+
|
|
81
|
+
CONTROL_GROUP = {
|
|
82
|
+
'type' => 'object',
|
|
83
|
+
'additionalProperties' => false,
|
|
84
|
+
'properties' => {
|
|
85
|
+
'id' => { 'type' => 'string' },
|
|
86
|
+
'title' => { 'type' => 'string', 'optional' => true },
|
|
87
|
+
'controls' => { 'type' => 'array', 'items' => { 'type' => 'string' } },
|
|
88
|
+
},
|
|
89
|
+
}.freeze
|
|
90
|
+
|
|
91
|
+
PROFILE = {
|
|
92
|
+
'type' => 'object',
|
|
93
|
+
'additionalProperties' => false,
|
|
94
|
+
'properties' => {
|
|
95
|
+
'name' => { 'type' => 'string' },
|
|
96
|
+
'version' => { 'type' => 'string', 'optional' => true },
|
|
97
|
+
'sha256' => { 'type' => 'string', 'optional' => false },
|
|
98
|
+
|
|
99
|
+
'title' => { 'type' => 'string', 'optional' => true },
|
|
100
|
+
'maintainer' => { 'type' => 'string', 'optional' => true },
|
|
101
|
+
'copyright' => { 'type' => 'string', 'optional' => true },
|
|
102
|
+
'copyright_email' => { 'type' => 'string', 'optional' => true },
|
|
103
|
+
'license' => { 'type' => 'string', 'optional' => true },
|
|
104
|
+
'summary' => { 'type' => 'string', 'optional' => true },
|
|
105
|
+
|
|
106
|
+
'supports' => {
|
|
107
|
+
'type' => 'array',
|
|
108
|
+
'items' => SUPPORTS,
|
|
109
|
+
'optional' => true,
|
|
110
|
+
},
|
|
111
|
+
'controls' => {
|
|
112
|
+
'type' => 'array',
|
|
113
|
+
'items' => CONTROL,
|
|
114
|
+
},
|
|
115
|
+
'groups' => {
|
|
116
|
+
'type' => 'array',
|
|
117
|
+
'items' => CONTROL_GROUP,
|
|
118
|
+
},
|
|
119
|
+
'attributes' => {
|
|
120
|
+
'type' => 'array',
|
|
121
|
+
# TODO: more detailed specification needed
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
}.freeze
|
|
125
|
+
|
|
126
|
+
EXEC_JSON = {
|
|
127
|
+
'type' => 'object',
|
|
128
|
+
'additionalProperties' => false,
|
|
129
|
+
'properties' => {
|
|
130
|
+
'platform' => PLATFORM,
|
|
131
|
+
'profiles' => {
|
|
132
|
+
'type' => 'array',
|
|
133
|
+
'items' => PROFILE,
|
|
134
|
+
},
|
|
135
|
+
'statistics' => STATISTICS,
|
|
136
|
+
'version' => { 'type' => 'string' },
|
|
137
|
+
|
|
138
|
+
# DEPRECATED PROPERTIES!! These will be removed with the next major version bump
|
|
139
|
+
'controls' => 'array',
|
|
140
|
+
'other_checks' => 'array',
|
|
141
|
+
},
|
|
142
|
+
}.freeze
|
|
143
|
+
|
|
144
|
+
MIN_CONTROL = {
|
|
145
|
+
'type' => 'object',
|
|
146
|
+
'additionalProperties' => false,
|
|
147
|
+
'properties' => {
|
|
148
|
+
'id' => { 'type' => 'string' },
|
|
149
|
+
'profile_id' => { 'type' => %w{string null} },
|
|
150
|
+
'status' => { 'type' => 'string' },
|
|
151
|
+
'code_desc' => { 'type' => 'string' },
|
|
152
|
+
'skip_message' => { 'type' => 'string', 'optional' => true },
|
|
153
|
+
'resource' => { 'type' => 'string', 'optional' => true },
|
|
154
|
+
},
|
|
155
|
+
}.freeze
|
|
156
|
+
|
|
157
|
+
EXEC_JSONMIN = {
|
|
158
|
+
'type' => 'object',
|
|
159
|
+
'additionalProperties' => false,
|
|
160
|
+
'properties' => {
|
|
161
|
+
'statistics' => STATISTICS,
|
|
162
|
+
'version' => { 'type' => 'string' },
|
|
163
|
+
'controls' => {
|
|
164
|
+
'type' => 'array',
|
|
165
|
+
'items' => MIN_CONTROL,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
}.freeze
|
|
169
|
+
|
|
170
|
+
LIST = {
|
|
171
|
+
'exec-json' => EXEC_JSON,
|
|
172
|
+
'exec-jsonmin' => EXEC_JSONMIN,
|
|
173
|
+
}.freeze
|
|
174
|
+
|
|
175
|
+
def self.names
|
|
176
|
+
LIST.keys
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def self.json(name)
|
|
180
|
+
v = LIST[name] ||
|
|
181
|
+
raise("Cannot find schema #{name.inspect}.")
|
|
182
|
+
JSON.dump(v)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
data/lib/inspec/secrets/yaml.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Secrets
|
|
|
9
9
|
attr_reader :attributes
|
|
10
10
|
|
|
11
11
|
def self.resolve(target)
|
|
12
|
-
unless target.is_a?(String) && File.file?(target) &&
|
|
12
|
+
unless target.is_a?(String) && File.file?(target) && ['.yml', '.yaml'].include?(File.extname(target).downcase)
|
|
13
13
|
return nil
|
|
14
14
|
end
|
|
15
15
|
new(target)
|
|
@@ -18,6 +18,13 @@ module Secrets
|
|
|
18
18
|
# array of yaml file paths
|
|
19
19
|
def initialize(target)
|
|
20
20
|
@attributes = ::YAML.load_file(target)
|
|
21
|
+
|
|
22
|
+
if @attributes == false || !@attributes.is_a?(Hash)
|
|
23
|
+
Inspec::Log.warn("#{self.class} unable to parse #{target}: invalid YAML or contents is not a Hash")
|
|
24
|
+
@attributes = nil
|
|
25
|
+
end
|
|
26
|
+
rescue => e
|
|
27
|
+
raise "Error reading Inspec attributes: #{e}"
|
|
21
28
|
end
|
|
22
29
|
end
|
|
23
30
|
end
|
data/lib/inspec/secrets.rb
CHANGED
data/lib/inspec/shell.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Inspec
|
|
|
9
9
|
# A pry based shell for inspec. Given a runner (with a configured backend and
|
|
10
10
|
# all that jazz), this shell will produce a pry shell from which you can run
|
|
11
11
|
# inspec/ruby commands that will be run within the context of the runner.
|
|
12
|
-
class Shell
|
|
12
|
+
class Shell # rubocop:disable Metrics/ClassLength
|
|
13
13
|
def initialize(runner)
|
|
14
14
|
@runner = runner
|
|
15
15
|
end
|
|
@@ -42,6 +42,8 @@ module Inspec
|
|
|
42
42
|
# Add a help menu as the default intro
|
|
43
43
|
Pry.hooks.add_hook(:before_session, 'inspec_intro') do
|
|
44
44
|
intro
|
|
45
|
+
print_target_info
|
|
46
|
+
puts
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
# Track the rules currently registered and what their merge count is.
|
|
@@ -79,7 +81,7 @@ module Inspec
|
|
|
79
81
|
# determine min whitespace that can be removed
|
|
80
82
|
min = nil
|
|
81
83
|
example.lines.each do |line|
|
|
82
|
-
if line.strip.
|
|
84
|
+
if !line.strip.empty? # ignore empty lines
|
|
83
85
|
line_whitespace = line.length - line.lstrip.length
|
|
84
86
|
min = line_whitespace if min.nil? || line_whitespace < min
|
|
85
87
|
end
|
|
@@ -94,10 +96,20 @@ module Inspec
|
|
|
94
96
|
puts
|
|
95
97
|
end
|
|
96
98
|
|
|
97
|
-
def
|
|
98
|
-
|
|
99
|
+
def print_target_info
|
|
100
|
+
ctx = @runner.backend
|
|
101
|
+
puts <<EOF
|
|
102
|
+
You are currently running on:
|
|
103
|
+
|
|
104
|
+
OS platform: #{mark ctx.os[:name] || 'unknown'}
|
|
105
|
+
OS family: #{mark ctx.os[:family] || 'unknown'}
|
|
106
|
+
OS release: #{mark ctx.os[:release] || 'unknown'}
|
|
107
|
+
EOF
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def help(topic = nil)
|
|
111
|
+
if topic.nil?
|
|
99
112
|
|
|
100
|
-
ctx = @runner.backend
|
|
101
113
|
puts <<EOF
|
|
102
114
|
|
|
103
115
|
Available commands:
|
|
@@ -105,46 +117,104 @@ Available commands:
|
|
|
105
117
|
`[resource]` - run resource on target machine
|
|
106
118
|
`help resources` - show all available resources that can be used as commands
|
|
107
119
|
`help [resource]` - information about a specific resource
|
|
120
|
+
`help matchers` - show information about common matchers
|
|
108
121
|
`exit` - exit the InSpec shell
|
|
109
122
|
|
|
110
123
|
You can use resources in this environment to test the target machine. For example:
|
|
111
124
|
|
|
112
125
|
command('uname -a').stdout
|
|
113
|
-
file('/proc/cpuinfo').content => "value"
|
|
114
|
-
|
|
115
|
-
You are currently running on:
|
|
116
|
-
|
|
117
|
-
OS platform: #{mark ctx.os[:name] || 'unknown'}
|
|
118
|
-
OS family: #{mark ctx.os[:family] || 'unknown'}
|
|
119
|
-
OS release: #{mark ctx.os[:release] || 'unknown'}
|
|
126
|
+
file('/proc/cpuinfo').content => "value"
|
|
120
127
|
|
|
128
|
+
#{print_target_info}
|
|
121
129
|
EOF
|
|
122
|
-
elsif
|
|
123
|
-
resources
|
|
124
|
-
|
|
130
|
+
elsif topic == 'resources'
|
|
131
|
+
resources.sort.each do |resource|
|
|
132
|
+
puts " - #{resource}"
|
|
133
|
+
end
|
|
134
|
+
elsif topic == 'matchers'
|
|
135
|
+
print_matchers_help
|
|
136
|
+
elsif !Inspec::Resource.registry[topic].nil?
|
|
125
137
|
puts <<EOF
|
|
126
|
-
#{mark 'Name:'} #{
|
|
138
|
+
#{mark 'Name:'} #{topic}
|
|
127
139
|
|
|
128
140
|
#{mark 'Description:'}
|
|
129
141
|
|
|
130
|
-
#{Inspec::Resource.registry[
|
|
142
|
+
#{Inspec::Resource.registry[topic].desc}
|
|
131
143
|
|
|
132
144
|
#{mark 'Example:'}
|
|
133
|
-
#{print_example(Inspec::Resource.registry[
|
|
145
|
+
#{print_example(Inspec::Resource.registry[topic].example)}
|
|
134
146
|
|
|
135
147
|
#{mark 'Web Reference:'}
|
|
136
148
|
|
|
137
|
-
https://
|
|
149
|
+
https://www.inspec.io/docs/reference/resources/#{topic}
|
|
138
150
|
|
|
139
151
|
EOF
|
|
140
152
|
else
|
|
141
|
-
puts
|
|
142
|
-
resources
|
|
153
|
+
puts "The resource #{topic} does not exist. For a list of valid resources, type: help resources"
|
|
143
154
|
end
|
|
144
155
|
end
|
|
145
156
|
|
|
146
157
|
def resources
|
|
147
|
-
|
|
158
|
+
Inspec::Resource.registry.keys
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def print_matchers_help
|
|
162
|
+
puts <<-EOL
|
|
163
|
+
Matchers are used to compare resource values to expectations. While some
|
|
164
|
+
resources implement their own custom matchers, the following matchers are
|
|
165
|
+
common amongst all resources:
|
|
166
|
+
|
|
167
|
+
#{mark 'be'}
|
|
168
|
+
|
|
169
|
+
The #{mark 'be'} matcher can be used to compare numeric values.
|
|
170
|
+
|
|
171
|
+
its('size') { should be >= 10 }
|
|
172
|
+
|
|
173
|
+
#{mark 'cmp'}
|
|
174
|
+
|
|
175
|
+
The #{mark 'cmp'} matcher is like #{mark 'eq'} but less restrictive. It will try
|
|
176
|
+
to fit the resource value to the expectation.
|
|
177
|
+
|
|
178
|
+
"Protocol" likely returns a string, but cmp will ensure it's a number before
|
|
179
|
+
comparing:
|
|
180
|
+
|
|
181
|
+
its('Protocol') { should cmp 2 }
|
|
182
|
+
its('Protocol') { should cmp '2' }
|
|
183
|
+
|
|
184
|
+
"users" may return an array, but if it contains only one item, cmp will compare
|
|
185
|
+
it as a string or number as needed:
|
|
186
|
+
|
|
187
|
+
its('users') { should cmp 'root' }
|
|
188
|
+
|
|
189
|
+
cmp is not case-sensitive:
|
|
190
|
+
|
|
191
|
+
its('log_format') { should cmp 'raw' }
|
|
192
|
+
its('log_format') { should cmp 'RAW' }
|
|
193
|
+
|
|
194
|
+
#{mark 'eq'}
|
|
195
|
+
|
|
196
|
+
The #{mark 'eq'} matcher tests for exact equality of two values. Value type
|
|
197
|
+
(string, number, etc.) is important and must be the same. For a less-restrictive
|
|
198
|
+
comparison matcher, use the #{mark 'cmp'} matcher.
|
|
199
|
+
|
|
200
|
+
its('RSAAuthentication') { should_not eq 'no' }
|
|
201
|
+
|
|
202
|
+
#{mark 'include'}
|
|
203
|
+
|
|
204
|
+
The #{mark 'include'} matcher tests to see if a value is included in a list.
|
|
205
|
+
|
|
206
|
+
its('users') { should include 'my_user' }
|
|
207
|
+
|
|
208
|
+
#{mark 'match'}
|
|
209
|
+
|
|
210
|
+
The #{mark 'match'} matcher can be used to test a string for a match using a
|
|
211
|
+
regular expression.
|
|
212
|
+
|
|
213
|
+
its('content') { should_not match /^MyKey:\\s+some value/ }
|
|
214
|
+
|
|
215
|
+
For more examples, see: https://www.inspec.io/docs/reference/matchers/
|
|
216
|
+
|
|
217
|
+
EOL
|
|
148
218
|
end
|
|
149
219
|
end
|
|
150
220
|
end
|
data/lib/inspec/source_reader.rb
CHANGED
data/lib/inspec/version.rb
CHANGED
data/lib/inspec.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# copyright: 2015, Dominik Richter
|
|
3
|
-
# license: All rights reserved
|
|
4
3
|
# author: Dominik Richter
|
|
5
4
|
# author: Christoph Hartmann
|
|
6
5
|
|
|
@@ -8,6 +7,7 @@ libdir = File.dirname(__FILE__)
|
|
|
8
7
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
9
8
|
|
|
10
9
|
require 'inspec/version'
|
|
10
|
+
require 'inspec/exceptions'
|
|
11
11
|
require 'inspec/profile'
|
|
12
12
|
require 'inspec/rspec_json_formatter'
|
|
13
13
|
require 'inspec/rule'
|