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/docs/ruby_usage.md CHANGED
@@ -152,3 +152,53 @@ describe command('ls -al /') do
152
152
  its('exit_status') { should eq 0 }
153
153
  end
154
154
  ```
155
+
156
+ ## Shelling out in tests
157
+
158
+ When writing tests you can not use standard ruby methods to shellout as it tries to execute those commands locally.
159
+ However, the `command` resource has a `.stdout` method that will allow you to manipulate the results.
160
+ Using the above example, you could check the writes on several subdirectories.
161
+
162
+ ### Example 1:
163
+ ```ruby
164
+ $ inspec shell
165
+ Welcome to the interactive InSpec Shell
166
+ To find out how to use it, type: help
167
+
168
+ inspec> output=command('echo test').stdout
169
+ => "test\n"
170
+ inspec> describe command('echo test') do
171
+ inspec> its('stdout') { should eq output }
172
+ inspec> end
173
+
174
+ Profile: inspec-shell
175
+ Version: (not specified)
176
+
177
+ Command echo
178
+ ✔ test stdout should eq "test\n"
179
+
180
+ Test Summary: 1 successful, 0 failures, 0 skipped
181
+ ```
182
+
183
+ ### Example 2:
184
+ ```ruby
185
+ $ inspec shell
186
+ Welcome to the interactive InSpec Shell
187
+ To find out how to use it, type: help
188
+
189
+ inspec> dirs = command('ls -d /home/gordon/git/inspec/docs').stdout.split("\n")
190
+ => ["/home/gordon/git/inspec/docs"]
191
+ inspec> dirs.each do |dir|
192
+ inspec> describe directory(dir) do
193
+ inspec> its('mode') { should cmp '0775' }
194
+ inspec> end
195
+ inspec> end
196
+
197
+ Profile: inspec-shell
198
+ Version: (not specified)
199
+
200
+ File /home/gordon/git/inspec/docs/
201
+ ✔ mode should cmp == "0775"
202
+
203
+ Test Summary: 1 successful, 0 failures, 0 skipped
204
+ ```
@@ -28,12 +28,10 @@ vs:
28
28
 
29
29
  Ignoring case sensitivity:
30
30
 
31
- .. code-block:: ruby
32
-
33
- describe some_resource do
34
- its('setting') { should cmp 'raw' }
35
- its('setting') { should cmp 'RAW' }
36
- end
31
+ describe some_resource do
32
+ its('setting') { should cmp 'raw' }
33
+ its('setting') { should cmp 'RAW' }
34
+ end
37
35
 
38
36
  Printing octal values:
39
37
 
@@ -7,13 +7,59 @@ This example shows the use of InSpec [profile](../../docs/profiles.rst) inherita
7
7
  InSpec ships with built-in features to verify a profile structure.
8
8
 
9
9
  ```bash
10
- $ inspec check examples/inheritance --profiles-path examples
10
+ $ inspec check examples/inheritance
11
11
  ```
12
12
 
13
13
  ## Execute a profile
14
14
 
15
- To run a profile on a local machine use `inspec exec /path/to/profile`.
15
+ To run a profile on a local machine use `inspec exec /path/to/profile`. All dependencies are automatically resolved.
16
16
 
17
17
  ```bash
18
- $ inspec exec examples/inheritance --profiles-path examples
18
+ $ inspec exec examples/inheritance
19
+ ```
20
+
21
+ ## Set attributes for dependent profiles
22
+
23
+ Without setting attributes, an `inspec exec` would return the following:
24
+
25
+ ```
26
+ $ inspec git:(master) ✗ b inspec exec examples/inheritance
27
+
28
+ Profile: InSpec example inheritance (inheritance)
29
+ Version: 1.0.0
30
+ Target: local://
31
+
32
+
33
+ ○ gordon-1.0: Verify the version number of Gordon (1 skipped)
34
+ ○ Can't find file "/tmp/gordon/config.yaml"
35
+ ✔ File content should match nil
36
+ ✔ ssh-1: Allow only SSH Protocol 2
37
+ ✔ File /bin/sh should be owned by "root"
38
+
39
+ File /tmp
40
+ ✔ should be directory
41
+ alice should
42
+ ✖ eq "bob"
43
+
44
+ expected: "bob"
45
+ got: "alice"
46
+
47
+ (compared using ==)
48
+
49
+ should eq
50
+ ✖ "secret"
51
+
52
+ expected: "secret"
53
+ got: nil
54
+
55
+ (compared using ==)
56
+
57
+
58
+ Test Summary: 3 successful, 2 failures, 1 skipped
59
+ ```
60
+
61
+ To pass in attributes, just call:
62
+
63
+ ```
64
+ $ inspec exec examples/inheritance --attrs examples/profile-attribute.yml
19
65
  ```
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2016, Chef Software, Inc.
3
- # license: All rights reserved
4
3
 
4
+ # manipulate controls of `profile`
5
5
  include_controls 'profile' do
6
6
  skip_control 'tmp-1.0'
7
7
 
@@ -9,3 +9,6 @@ include_controls 'profile' do
9
9
  impact 0.0
10
10
  end
11
11
  end
12
+
13
+ # load all controls of `profile-attribute`
14
+ include_controls 'profile-attribute'
@@ -3,7 +3,7 @@ title: InSpec example inheritance
3
3
  maintainer: Chef Software, Inc.
4
4
  copyright: Chef Software, Inc.
5
5
  copyright_email: support@chef.io
6
- license: Apache 2 license
6
+ license: Apache-2.0
7
7
  summary: Demonstrates the use of InSpec profile inheritance
8
8
  version: 1.0.0
9
9
  supports:
@@ -11,3 +11,5 @@ supports:
11
11
  depends:
12
12
  - name: profile
13
13
  path: ../profile
14
+ - name: profile-attribute
15
+ path: ../profile-attribute
@@ -5,7 +5,33 @@ from non-local sources such as Git or an HTTP url. This feature can
5
5
  be used to build up a environment-wide profile that is based on more
6
6
  specific profiles managed by others.
7
7
 
8
- # WARNING
8
+ InSpec supports multiple profile locations:
9
9
 
10
- This profile likely does not work yet. It exists as a target for
11
- ongoing development work.
10
+ ```
11
+ depends:
12
+ # defaults to supermarket
13
+ - name: hardening/ssh-hardening
14
+ # remote tar or zip file
15
+ - name: os-hardening
16
+ url: https://github.com/dev-sec/tests-os-hardening/archive/master.zip
17
+ # git
18
+ - git: https://github.com/dev-sec/ssl-baseline.git
19
+ - name: windows-patch-benchmark
20
+ git: https://github.com/chris-rock/windows-patch-benchmark.git
21
+ # Chef Compliance
22
+ - name: linux
23
+ compliance: base/linux
24
+ ```
25
+
26
+ You could use those dependencies in your `example.rb`:
27
+
28
+ ```
29
+
30
+ include_controls 'hardening/ssh-hardening'
31
+ include_controls 'os-hardening'
32
+ include_controls 'ssl-baseline'
33
+ include_controls 'linux'
34
+ include_controls 'windows-patch-benchmark'
35
+ ```
36
+
37
+ Further details are described in our [InSpec Docs](https://www.inspec.io/docs/reference/profiles/)
@@ -1,8 +1,13 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2015, The Authors
3
- # license: All rights reserved
4
- include_controls 'ssh-hardening'
5
- include_controls 'os-hardening'
6
- include_controls 'ssl-benchmark'
7
- include_controls 'linux'
3
+
4
+ # import full profile
5
+ include_controls 'dev-sec/ssh-baseline'
6
+
7
+ # select only individual controls
8
+ include_controls 'ssl-baseline' do
9
+ control "tls1.2"
10
+ end
11
+
12
+ # inspec knows that it cannot run Windows tests on Linux
8
13
  include_controls 'windows-patch-benchmark'
@@ -3,15 +3,11 @@ title: Meta Compliance Profile
3
3
  maintainer: InSpec Authors
4
4
  copyright: InSpec Authors
5
5
  copyright_email: support@chef.io
6
- license: Apache 2
6
+ license: Apache-2.0
7
7
  summary: InSpec Profile that is only consuming dependencies
8
8
  version: 0.2.0
9
9
  depends:
10
- - name: hardening/ssh-hardening # defaults to supermarket
11
- - name: os-hardening
12
- url: https://github.com/dev-sec/tests-os-hardening/archive/master.zip
13
- - git: https://github.com/dev-sec/ssl-benchmark.git
10
+ - name: dev-sec/ssh-baseline # defaults to supermarket
11
+ - url: https://github.com/dev-sec/ssl-baseline
14
12
  - name: windows-patch-benchmark
15
- git: https://github.com/chris-rock/windows-patch-benchmark.git
16
- - name: linux
17
- compliance: base/linux
13
+ url: https://github.com/chris-rock/windows-patch-benchmark
@@ -1,6 +1,6 @@
1
1
  # Example InSpec Profile
2
2
 
3
- This example shows the implementation of an InSpec [profile](../../docs/profiles.rst).
3
+ This example shows the implementation of an InSpec [profile](../../docs/profiles.md).
4
4
 
5
5
  ## Verify a profile
6
6
 
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2015, Chef Software, Inc.
3
- # license: All rights reserved
4
3
 
5
4
  title '/tmp profile'
6
5
 
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # copyright: 2016, Chef Software, Inc.
3
- # license: All rights reserved
4
3
 
5
4
  title 'Gordon Config Checks'
6
5
 
@@ -3,7 +3,7 @@ title: InSpec Example Profile
3
3
  maintainer: Chef Software, Inc.
4
4
  copyright: Chef Software, Inc.
5
5
  copyright_email: support@chef.io
6
- license: Apache 2 license
6
+ license: Apache-2.0
7
7
  summary: Demonstrates the use of InSpec Compliance Profile
8
8
  version: 1.0.0
9
9
  supports:
@@ -3,6 +3,6 @@ title: InSpec Profile
3
3
  maintainer: The Authors
4
4
  copyright: The Authors
5
5
  copyright_email: you@example.com
6
- license: All Rights Reserved
6
+ license: Apache-2.0
7
7
  summary: An InSpec Compliance Profile
8
8
  version: 0.1.0
@@ -0,0 +1,29 @@
1
+ # Example InSpec Profile with Sensitive failures
2
+
3
+ This profile demostrates resources flagged as sensitive
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ $ inspec exec examples/profile-sensitive
9
+ ....
10
+
11
+ bob should
12
+ ∅ eq "billy"
13
+
14
+ expected: "billy"
15
+ got: "bob"
16
+
17
+ (compared using ==)
18
+
19
+ sensitivepassword should
20
+ ∅ eq "secret"
21
+ *** sensitive output suppressed ***
22
+ bob should
23
+ ✔ eq "bob"
24
+ sensitivepassword should
25
+ ✔ eq "sensitivepassword"
26
+
27
+ Test Summary: 2 successful, 2 failures, 0 skipped
28
+
29
+ ```
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ describe 'bob' do
4
+ it { should eq 'billy' }
5
+ end
6
+
7
+ describe 'sensitivepassword', :sensitive do
8
+ it { should eq 'secret' }
9
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ describe 'bob' do
4
+ it { should eq 'bob' }
5
+ end
6
+
7
+ describe 'sensitivepassword', :sensitive do
8
+ it { should eq 'sensitivepassword' }
9
+ end
@@ -0,0 +1,8 @@
1
+ name: profile-sensitive
2
+ title: InSpec Sensitive Profile
3
+ maintainer: The Authors
4
+ copyright: The Authors
5
+ copyright_email: you@example.com
6
+ license: Apache-2.0
7
+ summary: An InSpec Compliance Profile
8
+ version: 0.1.0
data/inspec.gemspec CHANGED
@@ -24,7 +24,9 @@ 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.add_dependency 'train', '>=0.19.1', '<1.0'
27
+ spec.required_ruby_version = '>= 2.1'
28
+
29
+ spec.add_dependency 'train', '~> 0.26'
28
30
  spec.add_dependency 'thor', '~> 0.19'
29
31
  spec.add_dependency 'json', '>= 1.8', '< 3.0'
30
32
  spec.add_dependency 'rainbow', '~> 2'
@@ -35,6 +37,12 @@ Gem::Specification.new do |spec|
35
37
  spec.add_dependency 'pry', '~> 0'
36
38
  spec.add_dependency 'hashie', '~> 3.4'
37
39
  spec.add_dependency 'mixlib-log'
38
- spec.add_dependency 'sslshake', '~> 1'
40
+ spec.add_dependency 'sslshake', '~> 1.2'
39
41
  spec.add_dependency 'parallel', '~> 1.9'
42
+ spec.add_dependency 'faraday', '>=0.9.0'
43
+ spec.add_dependency 'toml', '~> 0.1'
44
+ spec.add_dependency 'addressable', '~> 2.4'
45
+ spec.add_dependency 'parslet', '~> 1.5'
46
+ spec.add_dependency 'semverse'
47
+ spec.add_dependency 'htmlentities'
40
48
  end
@@ -0,0 +1 @@
1
+ # TODO
@@ -0,0 +1,284 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'base64'
4
+ require 'openssl'
5
+ require 'pathname'
6
+ require 'set'
7
+ require 'tempfile'
8
+ require 'yaml'
9
+
10
+ # Notes:
11
+ #
12
+ # Generate keys
13
+ # The initial implementation uses 2048 bit RSA key pairs (public + private).
14
+ # Public keys must be available for a customer to install and verify an artifact.
15
+ # Private keys should be stored in a secure location and NOT be distributed.
16
+ # (They're only for creating artifacts).
17
+ #
18
+ #
19
+ # .IAF file format
20
+ # .iaf = "Inspec Artifact File", easy to rename if you'd like something more appropriate.
21
+ # The iaf file wraps a binary artifact with some metadata. The first implementation
22
+ # looks like this:
23
+ #
24
+ # INSPEC-PROFILE-1
25
+ # name_of_signing_key
26
+ # algorithm
27
+ # signature
28
+ # <empty line>
29
+ # binary-blob
30
+ # <eof>
31
+ #
32
+ # Let's look at each line:
33
+ # INSPEC-PROFILE-1:
34
+ # This is the artifact version descriptor. It should't change unless the
35
+ # format of the archive changes.
36
+ #
37
+ # name_of_signing_key
38
+ # The name of the public key that can be used to verify an artifact
39
+ #
40
+ # algorithm
41
+ # The digest used to sign, I picked SHA512 to start with.
42
+ # If we support multiple digests, we'll need to have the verify() method
43
+ # support each digest.
44
+ #
45
+ # signature
46
+ # The result of passing the binary artifact through the digest algorithm above.
47
+ # Result is base64 encoded.
48
+ #
49
+ # <empty line>
50
+ # We use an empty line to separate artifact header from artifact body (binary blob).
51
+ # The artifact body can be anything you like.
52
+ #
53
+ # binary-blob
54
+ # A binary blob, most likely a .tar.gz or tar.xz file. We'll need to pick one and
55
+ # stick with it as part of the "INSPEC-PROFILE-1" artifact version. If we change block
56
+ # format, the artifact version descriptor must be incremented, and the sign()
57
+ # and verify() methods must be updated to support a newer version.
58
+ #
59
+ #
60
+ # Key revocation
61
+ # This implementation doesn't support key revocation. However, a customer
62
+ # can remove the public cert file before installation, and artifacts will then
63
+ # fail verification.
64
+ #
65
+ # Key locations
66
+ # This implementation uses the current working directory to find public and
67
+ # private keys. We should establish a common key directory (similar to /hab/cache/keys
68
+ # or ~/.hab/cache/keys in Habitat).
69
+ #
70
+ # Extracting artifacts outside of Inspec
71
+ # As in Habitat, the artifact format for Inspec allows the use of common
72
+ # Unix tools to read the header and body of an artifact.
73
+ # To extract the header from a .iaf:
74
+ # sed '/^$/q' foo.iaf
75
+ # To extract the raw content from a .iaf:
76
+ # sed '1,/^$/d' foo.iaf
77
+
78
+ module Artifact
79
+ KEY_BITS=2048
80
+ KEY_ALG=OpenSSL::PKey::RSA
81
+
82
+ INSPEC_PROFILE_VERSION_1='INSPEC-PROFILE-1'.freeze
83
+ INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'.freeze
84
+
85
+ ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
86
+ ARTIFACT_DIGEST_NAME='SHA512'.freeze
87
+
88
+ VALID_PROFILE_VERSIONS=Set.new [INSPEC_PROFILE_VERSION_1]
89
+ VALID_PROFILE_DIGESTS=Set.new [ARTIFACT_DIGEST_NAME]
90
+
91
+ SIGNED_PROFILE_SUFFIX='iaf'.freeze
92
+ SIGNED_REPORT_SUFFIX='iar'.freeze
93
+
94
+ # rubocop:disable Metrics/ClassLength
95
+ class CLI < Inspec::BaseCLI
96
+ namespace 'artifact'
97
+
98
+ # TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
99
+ def self.banner(command, _namespace = nil, _subcommand = false)
100
+ "#{basename} #{subcommand_prefix} #{command.usage}"
101
+ end
102
+
103
+ def self.subcommand_prefix
104
+ namespace
105
+ end
106
+
107
+ desc 'generate', 'Generate a RSA key pair for signing and verification'
108
+ option :keyname, type: :string, required: true,
109
+ desc: 'Desriptive name of key'
110
+ option :keydir, type: :string, default: './',
111
+ desc: 'Directory to search for keys'
112
+ def generate_keys
113
+ puts 'Generating keys'
114
+ keygen
115
+ end
116
+
117
+ desc 'sign-profile', 'Create a signed .iaf artifact'
118
+ option :profile, type: :string, required: true,
119
+ desc: 'Path to profile directory'
120
+ option :keyname, type: :string, required: true,
121
+ desc: 'Desriptive name of key'
122
+ def sign_profile
123
+ profile_sign
124
+ end
125
+
126
+ desc 'verify-profile', 'Verify a signed .iaf artifact'
127
+ option :infile, type: :string, required: true,
128
+ desc: '.iaf file to verify'
129
+ def verify_profile
130
+ profile_verify
131
+ end
132
+
133
+ desc 'install-profile', 'Verify and install a signed .iaf artifact'
134
+ option :infile, type: :string, required: true,
135
+ desc: '.iaf file to install'
136
+ option :destdir, type: :string, required: true,
137
+ desc: 'Installation directory'
138
+ def install_profile
139
+ profile_install
140
+ end
141
+
142
+ private
143
+
144
+ def keygen
145
+ key = KEY_ALG.new KEY_BITS
146
+ puts 'Generating private key'
147
+ open "#{options['keyname']}.pem.key", 'w' do |io| io.write key.to_pem end
148
+ puts 'Generating public key'
149
+ open "#{options['keyname']}.pem.pub", 'w' do |io| io.write key.public_key.to_pem end
150
+ end
151
+
152
+ def read_profile_metadata(path_to_profile)
153
+ begin
154
+ p = Pathname.new(path_to_profile)
155
+ p = p.join('inspec.yml')
156
+ if not p.exist?
157
+ raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
158
+ end
159
+ yaml = YAML.load_file(p.to_s)
160
+ yaml = yaml.to_hash
161
+
162
+ if not yaml.key? 'name'
163
+ raise 'Profile is invalid, name is not defined'
164
+ end
165
+
166
+ if not yaml.key? 'version'
167
+ raise 'Profile is invalid, version is not defined'
168
+ end
169
+ rescue => e
170
+ # rewrap it and pass it up to the CLI
171
+ raise "Error reading Inspec profile metadata: #{e}"
172
+ end
173
+
174
+ yaml
175
+ end
176
+
177
+ def profile_compress(path_to_profile, profile_md, workdir)
178
+ profile_name = profile_md['name']
179
+ profile_version = profile_md['version']
180
+ outfile_name = "#{workdir}/#{profile_name}-#{profile_version}.tar.gz"
181
+ `tar czf #{outfile_name} -C #{path_to_profile} .`
182
+ outfile_name
183
+ end
184
+
185
+ def profile_sign
186
+ Dir.mktmpdir do |workdir|
187
+ puts "Signing #{options['profile']} with key #{options['keyname']}"
188
+ path_to_profile = options['profile']
189
+ profile_md = read_profile_metadata(path_to_profile)
190
+ artifact_filename = "#{profile_md['name']}-#{profile_md['version']}.#{SIGNED_PROFILE_SUFFIX}"
191
+ tarfile = profile_compress(path_to_profile, profile_md, workdir)
192
+ content = IO.binread(tarfile)
193
+ signing_key = KEY_ALG.new File.read "#{options['keyname']}.pem.key"
194
+ sha = ARTIFACT_DIGEST.new
195
+ signature = signing_key.sign sha, content
196
+ # convert the signature to Base64
197
+ signature_base64 = Base64.encode64(signature)
198
+ tar_content = IO.binread(tarfile)
199
+ File.open(artifact_filename, 'wb') do |f|
200
+ f.puts(INSPEC_PROFILE_VERSION_1)
201
+ f.puts(options['keyname'])
202
+ f.puts(ARTIFACT_DIGEST_NAME)
203
+ f.puts(signature_base64)
204
+ f.puts('') # newline separates artifact header with body
205
+ f.write(tar_content)
206
+ end
207
+ puts "Successfully generated #{artifact_filename}"
208
+ end
209
+ end
210
+
211
+ def valid_header?(file_alg, file_version, file_keyname)
212
+ public_keyfile = "#{file_keyname}.pem.pub"
213
+ puts "Looking for #{public_keyfile} to verify artifact"
214
+ if not File.exist? public_keyfile
215
+ raise "Can't find #{public_keyfile}"
216
+ end
217
+
218
+ if not VALID_PROFILE_DIGESTS.member? file_alg
219
+ raise 'Invalid artifact digest algorithm detected'
220
+ end
221
+
222
+ if not VALID_PROFILE_VERSIONS.member? file_version
223
+ raise 'Invalid artifact version detected'
224
+ end
225
+ end
226
+
227
+ def verify(file_to_verifiy, &content_block)
228
+ f = File.open(file_to_verifiy, 'r')
229
+ file_version = f.readline.strip!
230
+ file_keyname = f.readline.strip!
231
+ file_alg = f.readline.strip!
232
+
233
+ file_sig = ''
234
+ # the signature is multi-line
235
+ while (line = f.readline) != "\n"
236
+ file_sig += line
237
+ end
238
+ file_sig.strip!
239
+ f.close
240
+
241
+ valid_header?(file_alg, file_version, file_keyname)
242
+
243
+ public_keyfile = "#{file_keyname}.pem.pub"
244
+ verification_key = KEY_ALG.new File.read public_keyfile
245
+
246
+ f = File.open(file_to_verifiy, 'r')
247
+ while f.readline != "\n" do end
248
+ content = f.read
249
+
250
+ signature = Base64.decode64(file_sig)
251
+ digest = ARTIFACT_DIGEST.new
252
+ if verification_key.verify digest, signature, content
253
+ content_block.yield(content)
254
+ else
255
+ puts 'Artifact is invalid'
256
+ end
257
+ end
258
+
259
+ def profile_verify
260
+ file_to_verifiy = options['infile']
261
+ puts "Verifying #{file_to_verifiy}"
262
+ verify(file_to_verifiy) do ||
263
+ puts 'Artifact is valid'
264
+ end
265
+ end
266
+
267
+ def profile_install
268
+ puts 'Installing profile'
269
+ file_to_verifiy = options['infile']
270
+ dest_dir = options['destdir']
271
+ verify(file_to_verifiy) do |content|
272
+ Dir.mktmpdir do |workdir|
273
+ tmpfile = Pathname.new(workdir).join('artifact_to_install.tar.gz')
274
+ File.write(tmpfile, content)
275
+ puts "Installing to #{dest_dir}"
276
+ `tar xzf #{tmpfile} -C #{dest_dir}`
277
+ end
278
+ end
279
+ end
280
+ end
281
+
282
+ # register the subcommand to Inspec CLI registry
283
+ Inspec::Plugins::CLI.add_subcommand(Artifact::CLI, 'artifact', 'artifact SUBCOMMAND ...', 'Sign, verify and install artifacts', {})
284
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+ # author: Dave Parfitt
3
+
4
+ libdir = File.dirname(__FILE__)
5
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
6
+
7
+ require 'inspec-artifact/cli'