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.
Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +933 -101
  3. data/Gemfile +8 -17
  4. data/MAINTAINERS.md +2 -1
  5. data/MAINTAINERS.toml +9 -4
  6. data/README.md +49 -28
  7. data/Rakefile +54 -39
  8. data/bin/inspec +1 -1
  9. data/docs/dsl_inspec.md +17 -4
  10. data/docs/dsl_resource.md +1 -1
  11. data/docs/habitat.md +192 -0
  12. data/docs/inspec_and_friends.md +4 -2
  13. data/docs/matchers.md +11 -0
  14. data/docs/migration.md +293 -0
  15. data/docs/profiles.md +124 -76
  16. data/docs/resources/aide_conf.md.erb +81 -0
  17. data/docs/resources/apache_conf.md.erb +10 -10
  18. data/docs/resources/apt.md.erb +13 -13
  19. data/docs/resources/audit_policy.md.erb +10 -10
  20. data/docs/resources/auditd_conf.md.erb +10 -10
  21. data/docs/resources/auditd_rules.md.erb +11 -11
  22. data/docs/resources/bash.md.erb +12 -12
  23. data/docs/resources/bond.md.erb +15 -15
  24. data/docs/resources/bridge.md.erb +11 -11
  25. data/docs/resources/bsd_service.md.erb +11 -11
  26. data/docs/resources/command.md.erb +23 -23
  27. data/docs/resources/crontab.md.erb +84 -0
  28. data/docs/resources/csv.md.erb +10 -10
  29. data/docs/resources/dh_params.md +191 -0
  30. data/docs/resources/directory.md.erb +8 -8
  31. data/docs/resources/docker.md.erb +160 -0
  32. data/docs/resources/docker_container.md.erb +89 -0
  33. data/docs/resources/docker_image.md.erb +86 -0
  34. data/docs/resources/etc_group.md.erb +16 -16
  35. data/docs/resources/etc_hosts.md.erb +62 -0
  36. data/docs/resources/file.md.erb +80 -58
  37. data/docs/resources/gem.md.erb +32 -13
  38. data/docs/resources/group.md.erb +12 -12
  39. data/docs/resources/grub_conf.md.erb +11 -11
  40. data/docs/resources/host.md.erb +27 -18
  41. data/docs/resources/http.md.erb +104 -0
  42. data/docs/resources/iis_app.md.erb +126 -0
  43. data/docs/resources/iis_site.md.erb +17 -17
  44. data/docs/resources/inetd_conf.md.erb +10 -10
  45. data/docs/resources/ini.md.erb +9 -9
  46. data/docs/resources/interface.md.erb +13 -13
  47. data/docs/resources/iptables.md.erb +21 -14
  48. data/docs/resources/json.md.erb +11 -11
  49. data/docs/resources/kernel_module.md.erb +73 -12
  50. data/docs/resources/kernel_parameter.md.erb +12 -12
  51. data/docs/resources/key_rsa.md.erb +70 -0
  52. data/docs/resources/launchd_service.md.erb +11 -11
  53. data/docs/resources/limits_conf.md.erb +10 -10
  54. data/docs/resources/login_def.md.erb +12 -12
  55. data/docs/resources/mount.md.erb +14 -14
  56. data/docs/resources/mssql_session.md.erb +62 -0
  57. data/docs/resources/mysql_conf.md.erb +14 -14
  58. data/docs/resources/mysql_session.md.erb +22 -10
  59. data/docs/resources/npm.md.erb +13 -13
  60. data/docs/resources/ntp_conf.md.erb +9 -9
  61. data/docs/resources/oneget.md.erb +11 -11
  62. data/docs/resources/oracledb_session.md.erb +53 -0
  63. data/docs/resources/os.md.erb +17 -17
  64. data/docs/resources/os_env.md.erb +12 -12
  65. data/docs/resources/package.md.erb +29 -16
  66. data/docs/resources/parse_config.md.erb +18 -18
  67. data/docs/resources/parse_config_file.md.erb +29 -23
  68. data/docs/resources/{etc_passwd.md.erb → passwd.md.erb} +17 -17
  69. data/docs/resources/pip.md.erb +15 -15
  70. data/docs/resources/port.md.erb +23 -23
  71. data/docs/resources/postgres_conf.md.erb +15 -13
  72. data/docs/resources/postgres_hba_conf.md.erb +104 -0
  73. data/docs/resources/postgres_ident_conf.md.erb +87 -0
  74. data/docs/resources/postgres_session.md.erb +28 -21
  75. data/docs/resources/powershell.md.erb +14 -14
  76. data/docs/resources/processes.md.erb +123 -0
  77. data/docs/resources/rabbitmq_config.md.erb +55 -0
  78. data/docs/resources/registry_key.md.erb +44 -21
  79. data/docs/resources/runit_service.md.erb +11 -11
  80. data/docs/resources/security_policy.md.erb +10 -10
  81. data/docs/resources/service.md.erb +18 -18
  82. data/docs/resources/{etc_shadow.md.erb → shadow.md.erb} +19 -19
  83. data/docs/resources/ssh_config.md.erb +13 -13
  84. data/docs/resources/sshd_config.md.erb +15 -15
  85. data/docs/resources/ssl.md.erb +13 -13
  86. data/docs/resources/sys_info.md.erb +10 -10
  87. data/docs/resources/systemd_service.md.erb +11 -11
  88. data/docs/resources/sysv_service.md.erb +11 -11
  89. data/docs/resources/upstart_service.md.erb +11 -11
  90. data/docs/resources/user.md.erb +20 -20
  91. data/docs/resources/users.md.erb +19 -19
  92. data/docs/resources/vbscript.md.erb +13 -13
  93. data/docs/resources/virtualization.md.erb +71 -0
  94. data/docs/resources/windows_feature.md.erb +10 -10
  95. data/docs/resources/windows_task.md.erb +103 -0
  96. data/docs/resources/wmi.md.erb +10 -10
  97. data/docs/resources/x509_certificate.md.erb +146 -0
  98. data/docs/resources/xinetd_conf.md.erb +17 -17
  99. data/docs/resources/xml.md.erb +75 -0
  100. data/docs/resources/yaml.md.erb +25 -11
  101. data/docs/resources/yum.md.erb +24 -16
  102. data/docs/resources/zfs_dataset.md.erb +63 -0
  103. data/docs/resources/zfs_pool.md.erb +57 -0
  104. data/docs/ruby_usage.md +50 -0
  105. data/docs/shared/matcher_cmp.md.erb +4 -6
  106. data/examples/inheritance/README.md +49 -3
  107. data/examples/inheritance/controls/example.rb +4 -1
  108. data/examples/inheritance/inspec.yml +3 -1
  109. data/examples/meta-profile/README.md +29 -3
  110. data/examples/meta-profile/controls/example.rb +10 -5
  111. data/examples/meta-profile/inspec.yml +4 -8
  112. data/examples/profile/README.md +1 -1
  113. data/examples/profile/controls/example.rb +0 -1
  114. data/examples/profile/controls/gordon.rb +0 -1
  115. data/examples/profile/inspec.yml +1 -1
  116. data/examples/profile-attribute/inspec.yml +1 -1
  117. data/examples/profile-sensitive/README.md +29 -0
  118. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -0
  119. data/examples/profile-sensitive/controls/sensitive.rb +9 -0
  120. data/examples/profile-sensitive/inspec.yml +8 -0
  121. data/inspec.gemspec +10 -2
  122. data/lib/bundles/inspec-artifact/README.md +1 -0
  123. data/lib/bundles/inspec-artifact/cli.rb +284 -0
  124. data/lib/bundles/inspec-artifact.rb +7 -0
  125. data/lib/bundles/inspec-compliance/README.md +44 -15
  126. data/lib/bundles/inspec-compliance/api.rb +135 -29
  127. data/lib/bundles/inspec-compliance/cli.rb +128 -21
  128. data/lib/bundles/inspec-compliance/configuration.rb +8 -0
  129. data/lib/bundles/inspec-compliance/http.rb +26 -19
  130. data/lib/bundles/inspec-compliance/target.rb +50 -25
  131. data/lib/bundles/inspec-habitat/cli.rb +31 -0
  132. data/lib/bundles/inspec-habitat/log.rb +10 -0
  133. data/lib/bundles/inspec-habitat/profile.rb +372 -0
  134. data/lib/bundles/inspec-habitat.rb +12 -0
  135. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +0 -1
  136. data/lib/bundles/inspec-init/templates/profile/inspec.yml +1 -1
  137. data/lib/bundles/inspec-supermarket/api.rb +7 -5
  138. data/lib/bundles/inspec-supermarket/cli.rb +2 -2
  139. data/lib/fetchers/git.rb +4 -2
  140. data/lib/fetchers/local.rb +4 -1
  141. data/lib/fetchers/url.rb +64 -10
  142. data/lib/inspec/archive/tar.rb +1 -1
  143. data/lib/inspec/backend.rb +26 -3
  144. data/lib/inspec/base_cli.rb +44 -7
  145. data/lib/inspec/cached_fetcher.rb +2 -2
  146. data/lib/inspec/cli.rb +34 -12
  147. data/lib/inspec/completions/fish.sh.erb +34 -0
  148. data/lib/inspec/control_eval_context.rb +0 -2
  149. data/lib/inspec/dependencies/cache.rb +0 -1
  150. data/lib/inspec/dependencies/dependency_set.rb +2 -2
  151. data/lib/inspec/dependencies/lockfile.rb +13 -6
  152. data/lib/inspec/dependencies/requirement.rb +6 -6
  153. data/lib/inspec/dependencies/resolver.rb +4 -4
  154. data/lib/inspec/dsl.rb +3 -5
  155. data/lib/inspec/env_printer.rb +9 -1
  156. data/lib/inspec/exceptions.rb +8 -0
  157. data/lib/inspec/fetcher.rb +1 -1
  158. data/lib/inspec/file_provider.rb +47 -11
  159. data/lib/inspec/library_eval_context.rb +1 -1
  160. data/lib/inspec/metadata.rb +62 -18
  161. data/lib/inspec/method_source.rb +24 -0
  162. data/lib/inspec/objects/attribute.rb +21 -0
  163. data/lib/inspec/objects/control.rb +21 -3
  164. data/lib/inspec/objects/each_loop.rb +2 -1
  165. data/lib/inspec/objects/list.rb +1 -1
  166. data/lib/inspec/objects/or_test.rb +17 -2
  167. data/lib/inspec/objects/tag.rb +27 -0
  168. data/lib/inspec/objects/test.rb +9 -8
  169. data/lib/inspec/objects.rb +1 -0
  170. data/lib/inspec/plugins/fetcher.rb +4 -5
  171. data/lib/inspec/plugins/resource.rb +1 -2
  172. data/lib/inspec/plugins/source_reader.rb +3 -3
  173. data/lib/inspec/plugins.rb +1 -1
  174. data/lib/inspec/polyfill.rb +0 -1
  175. data/lib/inspec/profile.rb +92 -23
  176. data/lib/inspec/profile_context.rb +1 -1
  177. data/lib/inspec/profile_vendor.rb +66 -0
  178. data/lib/inspec/resource.rb +29 -3
  179. data/lib/inspec/rspec_json_formatter.rb +672 -285
  180. data/lib/inspec/rule.rb +12 -16
  181. data/lib/inspec/runner.rb +26 -15
  182. data/lib/inspec/runner_rspec.rb +1 -0
  183. data/lib/inspec/runtime_profile.rb +26 -0
  184. data/lib/inspec/schema.rb +185 -0
  185. data/lib/inspec/secrets/yaml.rb +8 -1
  186. data/lib/inspec/secrets.rb +1 -1
  187. data/lib/inspec/shell.rb +92 -22
  188. data/lib/inspec/source_reader.rb +1 -1
  189. data/lib/inspec/version.rb +1 -1
  190. data/lib/inspec.rb +1 -1
  191. data/lib/matchers/matchers.rb +67 -17
  192. data/lib/resources/aide_conf.rb +162 -0
  193. data/lib/resources/apache.rb +0 -1
  194. data/lib/resources/apache_conf.rb +3 -3
  195. data/lib/resources/apt.rb +2 -1
  196. data/lib/resources/audit_policy.rb +0 -1
  197. data/lib/resources/auditd_conf.rb +1 -2
  198. data/lib/resources/auditd_rules.rb +5 -5
  199. data/lib/resources/bond.rb +1 -1
  200. data/lib/resources/bridge.rb +1 -1
  201. data/lib/resources/command.rb +5 -3
  202. data/lib/resources/crontab.rb +102 -0
  203. data/lib/resources/csv.rb +18 -1
  204. data/lib/resources/dh_params.rb +84 -0
  205. data/lib/resources/directory.rb +7 -3
  206. data/lib/resources/docker.rb +198 -0
  207. data/lib/resources/docker_container.rb +114 -0
  208. data/lib/resources/docker_image.rb +96 -0
  209. data/lib/resources/etc_group.rb +2 -3
  210. data/lib/resources/etc_hosts.rb +81 -0
  211. data/lib/resources/file.rb +88 -30
  212. data/lib/resources/gem.rb +26 -6
  213. data/lib/resources/groups.rb +4 -5
  214. data/lib/resources/grub_conf.rb +3 -4
  215. data/lib/resources/host.rb +175 -35
  216. data/lib/resources/http.rb +73 -0
  217. data/lib/resources/iis_app.rb +103 -0
  218. data/lib/resources/iis_site.rb +23 -0
  219. data/lib/resources/inetd_conf.rb +9 -4
  220. data/lib/resources/interface.rb +4 -3
  221. data/lib/resources/json.rb +37 -14
  222. data/lib/resources/kernel_module.rb +77 -10
  223. data/lib/resources/kernel_parameter.rb +0 -1
  224. data/lib/resources/key_rsa.rb +67 -0
  225. data/lib/resources/limits_conf.rb +3 -4
  226. data/lib/resources/login_def.rb +2 -3
  227. data/lib/resources/mount.rb +34 -4
  228. data/lib/resources/mssql_session.rb +81 -12
  229. data/lib/resources/mysql.rb +0 -1
  230. data/lib/resources/mysql_conf.rb +1 -2
  231. data/lib/resources/mysql_session.rb +18 -7
  232. data/lib/resources/nginx_conf.rb +95 -0
  233. data/lib/resources/ntp_conf.rb +2 -3
  234. data/lib/resources/oracledb_session.rb +138 -0
  235. data/lib/resources/os_env.rb +7 -5
  236. data/lib/resources/package.rb +70 -13
  237. data/lib/resources/packages.rb +111 -0
  238. data/lib/resources/parse_config.rb +3 -4
  239. data/lib/resources/passwd.rb +4 -5
  240. data/lib/resources/pip.rb +29 -21
  241. data/lib/resources/port.rb +133 -14
  242. data/lib/resources/postgres.rb +53 -43
  243. data/lib/resources/postgres_conf.rb +40 -13
  244. data/lib/resources/postgres_hba_conf.rb +101 -0
  245. data/lib/resources/postgres_ident_conf.rb +79 -0
  246. data/lib/resources/postgres_session.rb +28 -20
  247. data/lib/resources/powershell.rb +2 -2
  248. data/lib/resources/processes.rb +61 -26
  249. data/lib/resources/rabbitmq_conf.rb +53 -0
  250. data/lib/resources/registry_key.rb +34 -11
  251. data/lib/resources/security_policy.rb +2 -2
  252. data/lib/resources/service.rb +17 -7
  253. data/lib/resources/ssh_conf.rb +17 -6
  254. data/lib/resources/ssl.rb +3 -4
  255. data/lib/resources/sys_info.rb +1 -1
  256. data/lib/resources/toml.rb +26 -0
  257. data/lib/resources/users.rb +41 -41
  258. data/lib/resources/virtualization.rb +252 -0
  259. data/lib/resources/windows_task.rb +106 -0
  260. data/lib/resources/x509_certificate.rb +143 -0
  261. data/lib/resources/xinetd.rb +18 -2
  262. data/lib/resources/xml.rb +27 -0
  263. data/lib/resources/yaml.rb +10 -2
  264. data/lib/resources/yum.rb +25 -7
  265. data/lib/resources/zfs_dataset.rb +60 -0
  266. data/lib/resources/zfs_pool.rb +49 -0
  267. data/lib/source_readers/flat.rb +2 -1
  268. data/lib/source_readers/inspec.rb +30 -11
  269. data/lib/utils/command_wrapper.rb +3 -3
  270. data/lib/utils/database_helpers.rb +77 -0
  271. data/lib/utils/erlang_parser.rb +192 -0
  272. data/lib/utils/filter.rb +2 -1
  273. data/lib/utils/filter_array.rb +0 -1
  274. data/lib/utils/find_files.rb +1 -2
  275. data/lib/utils/latest_version.rb +21 -0
  276. data/lib/utils/nginx_parser.rb +76 -0
  277. data/lib/utils/object_traversal.rb +5 -4
  278. data/lib/utils/parser.rb +23 -4
  279. data/lib/utils/plugin_registry.rb +3 -3
  280. data/lib/utils/simpleconfig.rb +25 -8
  281. data/lib/utils/spdx.rb +13 -0
  282. data/lib/utils/spdx.txt +344 -0
  283. metadata +168 -22
  284. data/docs/cli.md +0 -342
  285. data/docs/resources/process.md.erb +0 -73
  286. /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
- # TODO: replace this
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.strip.split("\n").map(&:strip)
242
- .map { |x| x.empty? ? "\n" : x }
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
- # read endpoints for secrets eg. yml file
119
- secrets_targets = options['attrs']
120
- unless secrets_targets.nil?
121
- secrets_targets.each do |target|
122
- secrets = Inspec::SecretsBackend.resolve(target)
123
- # merge hash values
124
- attributes = attributes.merge(secrets.attributes) unless secrets.nil? || secrets.attributes.nil?
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
- options['attributes'] = attributes
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
- fail "Could not resolve #{target} to valid input." if profile.nil?
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
- fail 'This profile requires InSpec version '\
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
- fail "This OS/platform (#{@backend.os[:name]}) is not supported by this profile."
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
- fail "A rule was registered with #{method_name.inspect}, "\
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
@@ -103,6 +103,7 @@ module Inspec
103
103
  'json' => 'InspecRspecJson',
104
104
  'json-rspec' => 'InspecRspecVanilla',
105
105
  'cli' => 'InspecRspecCli',
106
+ 'junit' => 'InspecRspecJUnit',
106
107
  }.freeze
107
108
 
108
109
  # Configure the output formatter and stream to be used with RSpec.
@@ -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
@@ -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) && target.end_with?('.yml')
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
@@ -10,7 +10,7 @@ module Inspec
10
10
 
11
11
  def self.secrets(version)
12
12
  if version != 1
13
- fail 'Only secrets version 1 is supported!'
13
+ raise 'Only secrets version 1 is supported!'
14
14
  end
15
15
  Inspec::Plugins::Secret
16
16
  end
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.length > 0 # ignore empty lines
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 help(resource = nil)
98
- if resource.nil?
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 resource == 'resources'
123
- resources
124
- elsif !Inspec::Resource.registry[resource].nil?
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:'} #{resource}
138
+ #{mark 'Name:'} #{topic}
127
139
 
128
140
  #{mark 'Description:'}
129
141
 
130
- #{Inspec::Resource.registry[resource].desc}
142
+ #{Inspec::Resource.registry[topic].desc}
131
143
 
132
144
  #{mark 'Example:'}
133
- #{print_example(Inspec::Resource.registry[resource].example)}
145
+ #{print_example(Inspec::Resource.registry[topic].example)}
134
146
 
135
147
  #{mark 'Web Reference:'}
136
148
 
137
- https://github.com/chef/inspec/blob/master/docs/resources.rst##{resource}
149
+ https://www.inspec.io/docs/reference/resources/#{topic}
138
150
 
139
151
  EOF
140
152
  else
141
- puts 'Only the following resources are available:'
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
- puts Inspec::Resource.registry.keys.join(' ')
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
@@ -19,7 +19,7 @@ module Inspec
19
19
 
20
20
  def self.source_reader(version)
21
21
  if version != 1
22
- fail 'Only source readers version 1 is supported!'
22
+ raise 'Only source readers version 1 is supported!'
23
23
  end
24
24
  Inspec::Plugins::SourceReader
25
25
  end
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.0.0'.freeze
7
+ VERSION = '1.35.1'.freeze
8
8
  end
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'