inspec 1.51.6 → 1.51.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (404) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +101 -101
  3. data/CHANGELOG.md +2915 -2902
  4. data/Gemfile +53 -53
  5. data/LICENSE +14 -14
  6. data/MAINTAINERS.md +31 -31
  7. data/MAINTAINERS.toml +47 -47
  8. data/README.md +419 -419
  9. data/Rakefile +167 -167
  10. data/bin/inspec +12 -12
  11. data/docs/.gitignore +2 -2
  12. data/docs/README.md +40 -40
  13. data/docs/dsl_inspec.md +258 -258
  14. data/docs/dsl_resource.md +93 -93
  15. data/docs/glossary.md +99 -99
  16. data/docs/habitat.md +191 -191
  17. data/docs/inspec_and_friends.md +107 -107
  18. data/docs/matchers.md +165 -165
  19. data/docs/migration.md +293 -293
  20. data/docs/plugin_kitchen_inspec.md +49 -49
  21. data/docs/profiles.md +370 -370
  22. data/docs/resources/aide_conf.md.erb +78 -78
  23. data/docs/resources/apache.md.erb +66 -66
  24. data/docs/resources/apache_conf.md.erb +67 -67
  25. data/docs/resources/apt.md.erb +70 -70
  26. data/docs/resources/audit_policy.md.erb +46 -46
  27. data/docs/resources/auditd.md.erb +78 -78
  28. data/docs/resources/auditd_conf.md.erb +68 -68
  29. data/docs/resources/auditd_rules.md.erb +116 -116
  30. data/docs/resources/bash.md.erb +74 -74
  31. data/docs/resources/bond.md.erb +89 -89
  32. data/docs/resources/bridge.md.erb +54 -54
  33. data/docs/resources/bsd_service.md.erb +65 -65
  34. data/docs/resources/command.md.erb +137 -137
  35. data/docs/resources/cpan.md.erb +77 -77
  36. data/docs/resources/cran.md.erb +63 -63
  37. data/docs/resources/crontab.md.erb +87 -87
  38. data/docs/resources/csv.md.erb +53 -53
  39. data/docs/resources/dh_params.md.erb +216 -216
  40. data/docs/resources/directory.md.erb +28 -28
  41. data/docs/resources/docker.md.erb +163 -163
  42. data/docs/resources/docker_container.md.erb +99 -99
  43. data/docs/resources/docker_image.md.erb +93 -93
  44. data/docs/resources/docker_service.md.erb +113 -113
  45. data/docs/resources/elasticsearch.md.erb +230 -230
  46. data/docs/resources/etc_fstab.md.erb +124 -124
  47. data/docs/resources/etc_group.md.erb +74 -74
  48. data/docs/resources/etc_hosts.md.erb +75 -75
  49. data/docs/resources/etc_hosts_allow.md.erb +73 -73
  50. data/docs/resources/etc_hosts_deny.md.erb +73 -73
  51. data/docs/resources/file.md.erb +512 -512
  52. data/docs/resources/filesystem.md.erb +40 -40
  53. data/docs/resources/firewalld.md.erb +105 -105
  54. data/docs/resources/gem.md.erb +78 -78
  55. data/docs/resources/group.md.erb +60 -60
  56. data/docs/resources/grub_conf.md.erb +101 -100
  57. data/docs/resources/host.md.erb +77 -77
  58. data/docs/resources/http.md.erb +104 -98
  59. data/docs/resources/iis_app.md.erb +120 -116
  60. data/docs/resources/iis_site.md.erb +132 -128
  61. data/docs/resources/inetd_conf.md.erb +95 -84
  62. data/docs/resources/ini.md.erb +72 -69
  63. data/docs/resources/interface.md.erb +55 -46
  64. data/docs/resources/iptables.md.erb +63 -63
  65. data/docs/resources/json.md.erb +61 -61
  66. data/docs/resources/kernel_module.md.erb +106 -106
  67. data/docs/resources/kernel_parameter.md.erb +58 -58
  68. data/docs/resources/key_rsa.md.erb +73 -73
  69. data/docs/resources/launchd_service.md.erb +56 -56
  70. data/docs/resources/limits_conf.md.erb +66 -66
  71. data/docs/resources/login_def.md.erb +62 -62
  72. data/docs/resources/mount.md.erb +68 -68
  73. data/docs/resources/mssql_session.md.erb +59 -59
  74. data/docs/resources/mysql_conf.md.erb +98 -98
  75. data/docs/resources/mysql_session.md.erb +73 -73
  76. data/docs/resources/nginx.md.erb +78 -78
  77. data/docs/resources/nginx_conf.md.erb +127 -127
  78. data/docs/resources/npm.md.erb +59 -59
  79. data/docs/resources/ntp_conf.md.erb +59 -59
  80. data/docs/resources/oneget.md.erb +52 -52
  81. data/docs/resources/oracledb_session.md.erb +51 -51
  82. data/docs/resources/os.md.erb +140 -140
  83. data/docs/resources/os_env.md.erb +77 -77
  84. data/docs/resources/package.md.erb +119 -119
  85. data/docs/resources/packages.md.erb +66 -66
  86. data/docs/resources/parse_config.md.erb +102 -102
  87. data/docs/resources/parse_config_file.md.erb +137 -137
  88. data/docs/resources/passwd.md.erb +140 -140
  89. data/docs/resources/pip.md.erb +66 -66
  90. data/docs/resources/port.md.erb +136 -136
  91. data/docs/resources/postgres_conf.md.erb +78 -78
  92. data/docs/resources/postgres_hba_conf.md.erb +92 -92
  93. data/docs/resources/postgres_ident_conf.md.erb +75 -75
  94. data/docs/resources/postgres_session.md.erb +68 -68
  95. data/docs/resources/powershell.md.erb +101 -101
  96. data/docs/resources/processes.md.erb +107 -107
  97. data/docs/resources/rabbitmq_config.md.erb +40 -40
  98. data/docs/resources/registry_key.md.erb +157 -157
  99. data/docs/resources/runit_service.md.erb +56 -56
  100. data/docs/resources/security_policy.md.erb +46 -46
  101. data/docs/resources/service.md.erb +120 -120
  102. data/docs/resources/shadow.md.erb +143 -143
  103. data/docs/resources/ssh_config.md.erb +79 -79
  104. data/docs/resources/sshd_config.md.erb +82 -82
  105. data/docs/resources/ssl.md.erb +118 -118
  106. data/docs/resources/sys_info.md.erb +41 -41
  107. data/docs/resources/systemd_service.md.erb +56 -56
  108. data/docs/resources/sysv_service.md.erb +56 -56
  109. data/docs/resources/upstart_service.md.erb +56 -56
  110. data/docs/resources/user.md.erb +139 -139
  111. data/docs/resources/users.md.erb +126 -126
  112. data/docs/resources/vbscript.md.erb +54 -54
  113. data/docs/resources/virtualization.md.erb +56 -56
  114. data/docs/resources/windows_feature.md.erb +46 -46
  115. data/docs/resources/windows_hotfix.md.erb +52 -52
  116. data/docs/resources/windows_task.md.erb +89 -89
  117. data/docs/resources/wmi.md.erb +80 -80
  118. data/docs/resources/x509_certificate.md.erb +150 -150
  119. data/docs/resources/xinetd_conf.md.erb +155 -155
  120. data/docs/resources/xml.md.erb +84 -84
  121. data/docs/resources/yaml.md.erb +68 -68
  122. data/docs/resources/yum.md.erb +97 -97
  123. data/docs/resources/zfs_dataset.md.erb +52 -52
  124. data/docs/resources/zfs_pool.md.erb +46 -46
  125. data/docs/ruby_usage.md +203 -203
  126. data/docs/shared/matcher_be.md.erb +1 -1
  127. data/docs/shared/matcher_cmp.md.erb +43 -43
  128. data/docs/shared/matcher_eq.md.erb +3 -3
  129. data/docs/shared/matcher_include.md.erb +1 -1
  130. data/docs/shared/matcher_match.md.erb +1 -1
  131. data/docs/shell.md +172 -172
  132. data/examples/README.md +8 -8
  133. data/examples/inheritance/README.md +65 -65
  134. data/examples/inheritance/controls/example.rb +14 -14
  135. data/examples/inheritance/inspec.yml +15 -15
  136. data/examples/kitchen-ansible/.kitchen.yml +25 -25
  137. data/examples/kitchen-ansible/Gemfile +19 -19
  138. data/examples/kitchen-ansible/README.md +53 -53
  139. data/examples/kitchen-ansible/files/nginx.repo +6 -6
  140. data/examples/kitchen-ansible/tasks/main.yml +16 -16
  141. data/examples/kitchen-ansible/test/integration/default/default.yml +5 -5
  142. data/examples/kitchen-ansible/test/integration/default/web_spec.rb +28 -28
  143. data/examples/kitchen-chef/.kitchen.yml +20 -20
  144. data/examples/kitchen-chef/Berksfile +3 -3
  145. data/examples/kitchen-chef/Gemfile +19 -19
  146. data/examples/kitchen-chef/README.md +27 -27
  147. data/examples/kitchen-chef/metadata.rb +7 -7
  148. data/examples/kitchen-chef/recipes/default.rb +6 -6
  149. data/examples/kitchen-chef/recipes/nginx.rb +30 -30
  150. data/examples/kitchen-chef/test/integration/default/web_spec.rb +28 -28
  151. data/examples/kitchen-puppet/.kitchen.yml +22 -22
  152. data/examples/kitchen-puppet/Gemfile +20 -20
  153. data/examples/kitchen-puppet/Puppetfile +25 -25
  154. data/examples/kitchen-puppet/README.md +53 -53
  155. data/examples/kitchen-puppet/manifests/site.pp +33 -33
  156. data/examples/kitchen-puppet/metadata.json +11 -11
  157. data/examples/kitchen-puppet/test/integration/default/web_spec.rb +28 -28
  158. data/examples/meta-profile/README.md +37 -37
  159. data/examples/meta-profile/controls/example.rb +13 -13
  160. data/examples/meta-profile/inspec.yml +13 -13
  161. data/examples/profile-attribute.yml +2 -2
  162. data/examples/profile-attribute/README.md +14 -14
  163. data/examples/profile-attribute/controls/example.rb +11 -11
  164. data/examples/profile-attribute/inspec.yml +8 -8
  165. data/examples/profile-sensitive/README.md +29 -29
  166. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -9
  167. data/examples/profile-sensitive/controls/sensitive.rb +9 -9
  168. data/examples/profile-sensitive/inspec.yml +8 -8
  169. data/examples/profile/README.md +48 -48
  170. data/examples/profile/controls/example.rb +23 -23
  171. data/examples/profile/controls/gordon.rb +36 -36
  172. data/examples/profile/controls/meta.rb +34 -34
  173. data/examples/profile/inspec.yml +10 -10
  174. data/examples/profile/libraries/gordon_config.rb +53 -53
  175. data/inspec.gemspec +47 -47
  176. data/lib/bundles/README.md +3 -3
  177. data/lib/bundles/inspec-artifact.rb +7 -7
  178. data/lib/bundles/inspec-artifact/README.md +1 -1
  179. data/lib/bundles/inspec-artifact/cli.rb +277 -277
  180. data/lib/bundles/inspec-compliance.rb +16 -16
  181. data/lib/bundles/inspec-compliance/.kitchen.yml +20 -20
  182. data/lib/bundles/inspec-compliance/README.md +185 -185
  183. data/lib/bundles/inspec-compliance/api.rb +316 -316
  184. data/lib/bundles/inspec-compliance/api/login.rb +152 -152
  185. data/lib/bundles/inspec-compliance/bootstrap.sh +41 -41
  186. data/lib/bundles/inspec-compliance/cli.rb +277 -277
  187. data/lib/bundles/inspec-compliance/configuration.rb +103 -103
  188. data/lib/bundles/inspec-compliance/http.rb +86 -86
  189. data/lib/bundles/inspec-compliance/support.rb +36 -36
  190. data/lib/bundles/inspec-compliance/target.rb +98 -98
  191. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +93 -93
  192. data/lib/bundles/inspec-habitat.rb +12 -12
  193. data/lib/bundles/inspec-habitat/cli.rb +36 -36
  194. data/lib/bundles/inspec-habitat/log.rb +10 -10
  195. data/lib/bundles/inspec-habitat/profile.rb +390 -390
  196. data/lib/bundles/inspec-init.rb +8 -8
  197. data/lib/bundles/inspec-init/README.md +31 -31
  198. data/lib/bundles/inspec-init/cli.rb +97 -97
  199. data/lib/bundles/inspec-init/templates/profile/README.md +3 -3
  200. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +19 -19
  201. data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -8
  202. data/lib/bundles/inspec-supermarket.rb +13 -13
  203. data/lib/bundles/inspec-supermarket/README.md +45 -45
  204. data/lib/bundles/inspec-supermarket/api.rb +84 -84
  205. data/lib/bundles/inspec-supermarket/cli.rb +65 -65
  206. data/lib/bundles/inspec-supermarket/target.rb +34 -34
  207. data/lib/fetchers/git.rb +163 -163
  208. data/lib/fetchers/local.rb +74 -74
  209. data/lib/fetchers/mock.rb +35 -35
  210. data/lib/fetchers/url.rb +204 -204
  211. data/lib/inspec.rb +24 -24
  212. data/lib/inspec/archive/tar.rb +29 -29
  213. data/lib/inspec/archive/zip.rb +19 -19
  214. data/lib/inspec/backend.rb +92 -92
  215. data/lib/inspec/base_cli.rb +324 -322
  216. data/lib/inspec/cached_fetcher.rb +66 -66
  217. data/lib/inspec/cli.rb +298 -298
  218. data/lib/inspec/completions/bash.sh.erb +45 -45
  219. data/lib/inspec/completions/fish.sh.erb +34 -34
  220. data/lib/inspec/completions/zsh.sh.erb +61 -61
  221. data/lib/inspec/control_eval_context.rb +179 -179
  222. data/lib/inspec/dependencies/cache.rb +72 -72
  223. data/lib/inspec/dependencies/dependency_set.rb +92 -92
  224. data/lib/inspec/dependencies/lockfile.rb +115 -115
  225. data/lib/inspec/dependencies/requirement.rb +123 -123
  226. data/lib/inspec/dependencies/resolver.rb +86 -86
  227. data/lib/inspec/describe.rb +27 -27
  228. data/lib/inspec/dsl.rb +66 -66
  229. data/lib/inspec/dsl_shared.rb +33 -33
  230. data/lib/inspec/env_printer.rb +157 -157
  231. data/lib/inspec/errors.rb +13 -13
  232. data/lib/inspec/exceptions.rb +12 -12
  233. data/lib/inspec/expect.rb +45 -45
  234. data/lib/inspec/fetcher.rb +45 -45
  235. data/lib/inspec/file_provider.rb +275 -275
  236. data/lib/inspec/formatters.rb +3 -3
  237. data/lib/inspec/formatters/base.rb +208 -208
  238. data/lib/inspec/formatters/json_rspec.rb +20 -20
  239. data/lib/inspec/formatters/show_progress.rb +12 -12
  240. data/lib/inspec/library_eval_context.rb +58 -58
  241. data/lib/inspec/log.rb +11 -11
  242. data/lib/inspec/metadata.rb +253 -253
  243. data/lib/inspec/method_source.rb +24 -24
  244. data/lib/inspec/objects.rb +14 -14
  245. data/lib/inspec/objects/attribute.rb +65 -65
  246. data/lib/inspec/objects/control.rb +61 -61
  247. data/lib/inspec/objects/describe.rb +92 -92
  248. data/lib/inspec/objects/each_loop.rb +36 -36
  249. data/lib/inspec/objects/list.rb +15 -15
  250. data/lib/inspec/objects/or_test.rb +40 -40
  251. data/lib/inspec/objects/ruby_helper.rb +15 -15
  252. data/lib/inspec/objects/tag.rb +27 -27
  253. data/lib/inspec/objects/test.rb +87 -87
  254. data/lib/inspec/objects/value.rb +27 -27
  255. data/lib/inspec/plugins.rb +60 -60
  256. data/lib/inspec/plugins/cli.rb +24 -24
  257. data/lib/inspec/plugins/fetcher.rb +86 -86
  258. data/lib/inspec/plugins/resource.rb +132 -132
  259. data/lib/inspec/plugins/secret.rb +15 -15
  260. data/lib/inspec/plugins/source_reader.rb +40 -40
  261. data/lib/inspec/polyfill.rb +12 -12
  262. data/lib/inspec/profile.rb +510 -510
  263. data/lib/inspec/profile_context.rb +207 -207
  264. data/lib/inspec/profile_vendor.rb +66 -66
  265. data/lib/inspec/reporters.rb +50 -33
  266. data/lib/inspec/reporters/base.rb +24 -23
  267. data/lib/inspec/reporters/cli.rb +395 -395
  268. data/lib/inspec/reporters/json.rb +134 -132
  269. data/lib/inspec/reporters/json_min.rb +48 -44
  270. data/lib/inspec/reporters/junit.rb +77 -77
  271. data/lib/inspec/require_loader.rb +33 -33
  272. data/lib/inspec/resource.rb +176 -176
  273. data/lib/inspec/rule.rb +266 -266
  274. data/lib/inspec/runner.rb +340 -337
  275. data/lib/inspec/runner_mock.rb +41 -41
  276. data/lib/inspec/runner_rspec.rb +163 -185
  277. data/lib/inspec/runtime_profile.rb +26 -26
  278. data/lib/inspec/schema.rb +186 -186
  279. data/lib/inspec/secrets.rb +19 -19
  280. data/lib/inspec/secrets/yaml.rb +30 -30
  281. data/lib/inspec/shell.rb +223 -223
  282. data/lib/inspec/shell_detector.rb +90 -90
  283. data/lib/inspec/source_reader.rb +29 -29
  284. data/lib/inspec/version.rb +8 -8
  285. data/lib/matchers/matchers.rb +397 -397
  286. data/lib/resources/aide_conf.rb +160 -160
  287. data/lib/resources/apache.rb +49 -49
  288. data/lib/resources/apache_conf.rb +158 -158
  289. data/lib/resources/apt.rb +150 -150
  290. data/lib/resources/audit_policy.rb +64 -64
  291. data/lib/resources/auditd.rb +233 -233
  292. data/lib/resources/auditd_conf.rb +56 -56
  293. data/lib/resources/auditd_rules.rb +205 -205
  294. data/lib/resources/bash.rb +36 -36
  295. data/lib/resources/bond.rb +69 -69
  296. data/lib/resources/bridge.rb +123 -123
  297. data/lib/resources/command.rb +69 -69
  298. data/lib/resources/cpan.rb +60 -60
  299. data/lib/resources/cran.rb +66 -66
  300. data/lib/resources/crontab.rb +169 -169
  301. data/lib/resources/csv.rb +58 -58
  302. data/lib/resources/dh_params.rb +83 -83
  303. data/lib/resources/directory.rb +25 -25
  304. data/lib/resources/docker.rb +239 -239
  305. data/lib/resources/docker_container.rb +92 -92
  306. data/lib/resources/docker_image.rb +86 -86
  307. data/lib/resources/docker_object.rb +57 -57
  308. data/lib/resources/docker_service.rb +94 -94
  309. data/lib/resources/elasticsearch.rb +168 -168
  310. data/lib/resources/etc_fstab.rb +102 -102
  311. data/lib/resources/etc_group.rb +157 -157
  312. data/lib/resources/etc_hosts.rb +81 -81
  313. data/lib/resources/etc_hosts_allow_deny.rb +122 -122
  314. data/lib/resources/file.rb +298 -298
  315. data/lib/resources/filesystem.rb +31 -31
  316. data/lib/resources/firewalld.rb +144 -144
  317. data/lib/resources/gem.rb +71 -71
  318. data/lib/resources/groups.rb +213 -213
  319. data/lib/resources/grub_conf.rb +237 -237
  320. data/lib/resources/host.rb +300 -300
  321. data/lib/resources/http.rb +252 -252
  322. data/lib/resources/iis_app.rb +103 -103
  323. data/lib/resources/iis_site.rb +147 -147
  324. data/lib/resources/inetd_conf.rb +63 -63
  325. data/lib/resources/ini.rb +29 -29
  326. data/lib/resources/interface.rb +130 -130
  327. data/lib/resources/iptables.rb +70 -70
  328. data/lib/resources/json.rb +115 -115
  329. data/lib/resources/kernel_module.rb +110 -110
  330. data/lib/resources/kernel_parameter.rb +58 -58
  331. data/lib/resources/key_rsa.rb +67 -67
  332. data/lib/resources/limits_conf.rb +56 -56
  333. data/lib/resources/login_def.rb +67 -67
  334. data/lib/resources/mount.rb +90 -90
  335. data/lib/resources/mssql_session.rb +103 -103
  336. data/lib/resources/mysql.rb +82 -82
  337. data/lib/resources/mysql_conf.rb +133 -133
  338. data/lib/resources/mysql_session.rb +72 -72
  339. data/lib/resources/nginx.rb +97 -97
  340. data/lib/resources/nginx_conf.rb +228 -228
  341. data/lib/resources/npm.rb +48 -48
  342. data/lib/resources/ntp_conf.rb +59 -59
  343. data/lib/resources/oneget.rb +72 -72
  344. data/lib/resources/oracledb_session.rb +140 -140
  345. data/lib/resources/os.rb +46 -46
  346. data/lib/resources/os_env.rb +76 -76
  347. data/lib/resources/package.rb +357 -357
  348. data/lib/resources/packages.rb +112 -112
  349. data/lib/resources/parse_config.rb +116 -116
  350. data/lib/resources/passwd.rb +96 -96
  351. data/lib/resources/pip.rb +89 -89
  352. data/lib/resources/platform.rb +112 -112
  353. data/lib/resources/port.rb +771 -771
  354. data/lib/resources/postgres.rb +132 -132
  355. data/lib/resources/postgres_conf.rb +122 -122
  356. data/lib/resources/postgres_hba_conf.rb +101 -101
  357. data/lib/resources/postgres_ident_conf.rb +79 -79
  358. data/lib/resources/postgres_session.rb +72 -72
  359. data/lib/resources/powershell.rb +58 -58
  360. data/lib/resources/processes.rb +204 -204
  361. data/lib/resources/rabbitmq_conf.rb +53 -53
  362. data/lib/resources/registry_key.rb +296 -296
  363. data/lib/resources/security_policy.rb +181 -181
  364. data/lib/resources/service.rb +784 -784
  365. data/lib/resources/shadow.rb +141 -141
  366. data/lib/resources/ssh_conf.rb +102 -102
  367. data/lib/resources/ssl.rb +99 -99
  368. data/lib/resources/sys_info.rb +26 -26
  369. data/lib/resources/toml.rb +32 -32
  370. data/lib/resources/users.rb +652 -652
  371. data/lib/resources/vbscript.rb +70 -70
  372. data/lib/resources/virtualization.rb +251 -251
  373. data/lib/resources/windows_feature.rb +85 -85
  374. data/lib/resources/windows_hotfix.rb +35 -35
  375. data/lib/resources/windows_task.rb +106 -106
  376. data/lib/resources/wmi.rb +114 -114
  377. data/lib/resources/x509_certificate.rb +143 -143
  378. data/lib/resources/xinetd.rb +112 -112
  379. data/lib/resources/xml.rb +45 -45
  380. data/lib/resources/yaml.rb +45 -45
  381. data/lib/resources/yum.rb +181 -181
  382. data/lib/resources/zfs_dataset.rb +60 -60
  383. data/lib/resources/zfs_pool.rb +49 -49
  384. data/lib/source_readers/flat.rb +39 -39
  385. data/lib/source_readers/inspec.rb +75 -75
  386. data/lib/utils/command_wrapper.rb +27 -27
  387. data/lib/utils/convert.rb +12 -12
  388. data/lib/utils/database_helpers.rb +77 -77
  389. data/lib/utils/erlang_parser.rb +192 -192
  390. data/lib/utils/filter.rb +272 -272
  391. data/lib/utils/filter_array.rb +27 -27
  392. data/lib/utils/find_files.rb +44 -44
  393. data/lib/utils/hash.rb +41 -41
  394. data/lib/utils/json_log.rb +18 -18
  395. data/lib/utils/latest_version.rb +22 -22
  396. data/lib/utils/modulator.rb +12 -12
  397. data/lib/utils/nginx_parser.rb +85 -85
  398. data/lib/utils/object_traversal.rb +49 -49
  399. data/lib/utils/parser.rb +274 -274
  400. data/lib/utils/plugin_registry.rb +93 -93
  401. data/lib/utils/simpleconfig.rb +132 -132
  402. data/lib/utils/spdx.rb +13 -13
  403. data/lib/utils/spdx.txt +343 -343
  404. metadata +2 -2
@@ -1,53 +1,53 @@
1
- require 'yaml'
2
-
3
- # Custom resource based on the InSpec resource DSL
4
- class GordonConfig < Inspec.resource(1)
5
- name 'gordon_config'
6
-
7
- desc "
8
- Gordon's resource description ...
9
- "
10
-
11
- example "
12
- describe gordon_config do
13
- its('version') { should eq('1.0') }
14
- its('file_size') { should > 1 }
15
- end
16
- "
17
-
18
- # Load the configuration file on initialization
19
- def initialize
20
- @params = {}
21
- @path = '/tmp/gordon/config.yaml'
22
- @file = inspec.file(@path)
23
- return skip_resource "Can't find file \"#{@path}\"" if !@file.file?
24
-
25
- # Protect from invalid YAML content
26
- begin
27
- @params = YAML.load(@file.content)
28
- # Add two extra matchers
29
- @params['file_size'] = @file.size
30
- @params['file_path'] = @path
31
- @params['ruby'] = 'RUBY IS HERE TO HELP ME!'
32
- rescue Exception
33
- return skip_resource "#{@file}: #{$!}"
34
- end
35
- end
36
-
37
- # Example method called by 'it { should exist }'
38
- # Returns true or false from the 'File.exists?' method
39
- def exists?
40
- return File.exists?(@path)
41
- end
42
-
43
- # Example matcher for the number of commas in the file
44
- def comma_count
45
- text = @file.content
46
- return text.count(',')
47
- end
48
-
49
- # Expose all parameters
50
- def method_missing(name)
51
- return @params[name.to_s]
52
- end
53
- end
1
+ require 'yaml'
2
+
3
+ # Custom resource based on the InSpec resource DSL
4
+ class GordonConfig < Inspec.resource(1)
5
+ name 'gordon_config'
6
+
7
+ desc "
8
+ Gordon's resource description ...
9
+ "
10
+
11
+ example "
12
+ describe gordon_config do
13
+ its('version') { should eq('1.0') }
14
+ its('file_size') { should > 1 }
15
+ end
16
+ "
17
+
18
+ # Load the configuration file on initialization
19
+ def initialize
20
+ @params = {}
21
+ @path = '/tmp/gordon/config.yaml'
22
+ @file = inspec.file(@path)
23
+ return skip_resource "Can't find file \"#{@path}\"" if !@file.file?
24
+
25
+ # Protect from invalid YAML content
26
+ begin
27
+ @params = YAML.load(@file.content)
28
+ # Add two extra matchers
29
+ @params['file_size'] = @file.size
30
+ @params['file_path'] = @path
31
+ @params['ruby'] = 'RUBY IS HERE TO HELP ME!'
32
+ rescue Exception
33
+ return skip_resource "#{@file}: #{$!}"
34
+ end
35
+ end
36
+
37
+ # Example method called by 'it { should exist }'
38
+ # Returns true or false from the 'File.exists?' method
39
+ def exists?
40
+ return File.exists?(@path)
41
+ end
42
+
43
+ # Example matcher for the number of commas in the file
44
+ def comma_count
45
+ text = @file.content
46
+ return text.count(',')
47
+ end
48
+
49
+ # Expose all parameters
50
+ def method_missing(name)
51
+ return @params[name.to_s]
52
+ end
53
+ end
@@ -1,47 +1,47 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'inspec/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = 'inspec'
8
- spec.version = Inspec::VERSION
9
- spec.authors = ['Dominik Richter']
10
- spec.email = ['dominik.richter@gmail.com']
11
- spec.summary = 'Infrastructure and compliance testing.'
12
- spec.description = 'InSpec provides a framework for creating end-to-end infrastructure tests. You can use it for integration or even compliance testing. Create fully portable test profiles and use them in your workflow to ensure stability and security. Integrate InSpec in your change lifecycle for local testing, CI/CD, and deployment verification.'
13
- spec.homepage = 'https://github.com/chef/inspec'
14
- spec.license = 'Apache-2.0'
15
-
16
- spec.files = %w{
17
- README.md Rakefile MAINTAINERS.toml MAINTAINERS.md LICENSE inspec.gemspec
18
- Gemfile CHANGELOG.md .rubocop.yml
19
- } + Dir.glob(
20
- '{bin,docs,examples,lib}/**/*', File::FNM_DOTMATCH
21
- ).reject { |f| File.directory?(f) }
22
-
23
- spec.executables = %w{inspec}
24
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
25
- spec.require_paths = ['lib']
26
-
27
- spec.required_ruby_version = '>= 2.3'
28
-
29
- spec.add_dependency 'train', '~> 0.32'
30
- spec.add_dependency 'thor', '~> 0.19'
31
- spec.add_dependency 'json', '>= 1.8', '< 3.0'
32
- spec.add_dependency 'method_source', '~> 0.8'
33
- spec.add_dependency 'rubyzip', '~> 1.1'
34
- spec.add_dependency 'rspec', '~> 3'
35
- spec.add_dependency 'rspec-its', '~> 1.2'
36
- spec.add_dependency 'pry', '~> 0'
37
- spec.add_dependency 'hashie', '~> 3.4'
38
- spec.add_dependency 'mixlib-log'
39
- spec.add_dependency 'sslshake', '~> 1.2'
40
- spec.add_dependency 'parallel', '~> 1.9'
41
- spec.add_dependency 'faraday', '>=0.9.0'
42
- spec.add_dependency 'tomlrb', '~> 1.2'
43
- spec.add_dependency 'addressable', '~> 2.4'
44
- spec.add_dependency 'parslet', '~> 1.5'
45
- spec.add_dependency 'semverse'
46
- spec.add_dependency 'htmlentities'
47
- end
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'inspec/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'inspec'
8
+ spec.version = Inspec::VERSION
9
+ spec.authors = ['Dominik Richter']
10
+ spec.email = ['dominik.richter@gmail.com']
11
+ spec.summary = 'Infrastructure and compliance testing.'
12
+ spec.description = 'InSpec provides a framework for creating end-to-end infrastructure tests. You can use it for integration or even compliance testing. Create fully portable test profiles and use them in your workflow to ensure stability and security. Integrate InSpec in your change lifecycle for local testing, CI/CD, and deployment verification.'
13
+ spec.homepage = 'https://github.com/chef/inspec'
14
+ spec.license = 'Apache-2.0'
15
+
16
+ spec.files = %w{
17
+ README.md Rakefile MAINTAINERS.toml MAINTAINERS.md LICENSE inspec.gemspec
18
+ Gemfile CHANGELOG.md .rubocop.yml
19
+ } + Dir.glob(
20
+ '{bin,docs,examples,lib}/**/*', File::FNM_DOTMATCH
21
+ ).reject { |f| File.directory?(f) }
22
+
23
+ spec.executables = %w{inspec}
24
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
25
+ spec.require_paths = ['lib']
26
+
27
+ spec.required_ruby_version = '>= 2.3'
28
+
29
+ spec.add_dependency 'train', '~> 0.32'
30
+ spec.add_dependency 'thor', '~> 0.19'
31
+ spec.add_dependency 'json', '>= 1.8', '< 3.0'
32
+ spec.add_dependency 'method_source', '~> 0.8'
33
+ spec.add_dependency 'rubyzip', '~> 1.1'
34
+ spec.add_dependency 'rspec', '~> 3'
35
+ spec.add_dependency 'rspec-its', '~> 1.2'
36
+ spec.add_dependency 'pry', '~> 0'
37
+ spec.add_dependency 'hashie', '~> 3.4'
38
+ spec.add_dependency 'mixlib-log'
39
+ spec.add_dependency 'sslshake', '~> 1.2'
40
+ spec.add_dependency 'parallel', '~> 1.9'
41
+ spec.add_dependency 'faraday', '>=0.9.0'
42
+ spec.add_dependency 'tomlrb', '~> 1.2'
43
+ spec.add_dependency 'addressable', '~> 2.4'
44
+ spec.add_dependency 'parslet', '~> 1.5'
45
+ spec.add_dependency 'semverse'
46
+ spec.add_dependency 'htmlentities'
47
+ end
@@ -1,3 +1,3 @@
1
- # InSpec Bundled Plugins
2
-
3
- This directory contains bundled InSpec plugins. Those plugins are shipped with InSpec temporarily only. Over the next months we are going to stabilize the InSpec Plugin API. Once this API reached stability, all bundled plugins will be externalized.
1
+ # InSpec Bundled Plugins
2
+
3
+ This directory contains bundled InSpec plugins. Those plugins are shipped with InSpec temporarily only. Over the next months we are going to stabilize the InSpec Plugin API. Once this API reached stability, all bundled plugins will be externalized.
@@ -1,7 +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'
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'
@@ -1 +1 @@
1
- # TODO
1
+ # TODO
@@ -1,277 +1,277 @@
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'
83
- INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'
84
-
85
- ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
86
- ARTIFACT_DIGEST_NAME='SHA512'
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'
92
- SIGNED_REPORT_SUFFIX='iar'
93
- class CLI < Inspec::BaseCLI
94
- namespace 'artifact'
95
-
96
- # TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
97
- def self.banner(command, _namespace = nil, _subcommand = false)
98
- "#{basename} #{subcommand_prefix} #{command.usage}"
99
- end
100
-
101
- def self.subcommand_prefix
102
- namespace
103
- end
104
-
105
- desc 'generate', 'Generate a RSA key pair for signing and verification'
106
- option :keyname, type: :string, required: true,
107
- desc: 'Desriptive name of key'
108
- option :keydir, type: :string, default: './',
109
- desc: 'Directory to search for keys'
110
- def generate_keys
111
- puts 'Generating keys'
112
- keygen
113
- end
114
-
115
- desc 'sign-profile', 'Create a signed .iaf artifact'
116
- option :profile, type: :string, required: true,
117
- desc: 'Path to profile directory'
118
- option :keyname, type: :string, required: true,
119
- desc: 'Desriptive name of key'
120
- def sign_profile
121
- profile_sign
122
- end
123
-
124
- desc 'verify-profile', 'Verify a signed .iaf artifact'
125
- option :infile, type: :string, required: true,
126
- desc: '.iaf file to verify'
127
- def verify_profile
128
- profile_verify
129
- end
130
-
131
- desc 'install-profile', 'Verify and install a signed .iaf artifact'
132
- option :infile, type: :string, required: true,
133
- desc: '.iaf file to install'
134
- option :destdir, type: :string, required: true,
135
- desc: 'Installation directory'
136
- def install_profile
137
- profile_install
138
- end
139
-
140
- private
141
-
142
- def keygen
143
- key = KEY_ALG.new KEY_BITS
144
- puts 'Generating private key'
145
- open "#{options['keyname']}.pem.key", 'w' do |io| io.write key.to_pem end
146
- puts 'Generating public key'
147
- open "#{options['keyname']}.pem.pub", 'w' do |io| io.write key.public_key.to_pem end
148
- end
149
-
150
- def read_profile_metadata(path_to_profile)
151
- begin
152
- p = Pathname.new(path_to_profile)
153
- p = p.join('inspec.yml')
154
- if not p.exist?
155
- raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
156
- end
157
- yaml = YAML.load_file(p.to_s)
158
- yaml = yaml.to_hash
159
-
160
- if not yaml.key? 'name'
161
- raise 'Profile is invalid, name is not defined'
162
- end
163
-
164
- if not yaml.key? 'version'
165
- raise 'Profile is invalid, version is not defined'
166
- end
167
- rescue => e
168
- # rewrap it and pass it up to the CLI
169
- raise "Error reading Inspec profile metadata: #{e}"
170
- end
171
-
172
- yaml
173
- end
174
-
175
- def profile_compress(path_to_profile, profile_md, workdir)
176
- profile_name = profile_md['name']
177
- profile_version = profile_md['version']
178
- outfile_name = "#{workdir}/#{profile_name}-#{profile_version}.tar.gz"
179
- `tar czf #{outfile_name} -C #{path_to_profile} .`
180
- outfile_name
181
- end
182
-
183
- def profile_sign
184
- Dir.mktmpdir do |workdir|
185
- puts "Signing #{options['profile']} with key #{options['keyname']}"
186
- path_to_profile = options['profile']
187
- profile_md = read_profile_metadata(path_to_profile)
188
- artifact_filename = "#{profile_md['name']}-#{profile_md['version']}.#{SIGNED_PROFILE_SUFFIX}"
189
- tarfile = profile_compress(path_to_profile, profile_md, workdir)
190
- content = IO.binread(tarfile)
191
- signing_key = KEY_ALG.new File.read "#{options['keyname']}.pem.key"
192
- sha = ARTIFACT_DIGEST.new
193
- signature = signing_key.sign sha, content
194
- # convert the signature to Base64
195
- signature_base64 = Base64.encode64(signature)
196
- tar_content = IO.binread(tarfile)
197
- File.open(artifact_filename, 'wb') do |f|
198
- f.puts(INSPEC_PROFILE_VERSION_1)
199
- f.puts(options['keyname'])
200
- f.puts(ARTIFACT_DIGEST_NAME)
201
- f.puts(signature_base64)
202
- f.puts('') # newline separates artifact header with body
203
- f.write(tar_content)
204
- end
205
- puts "Successfully generated #{artifact_filename}"
206
- end
207
- end
208
-
209
- def valid_header?(file_alg, file_version, file_keyname)
210
- public_keyfile = "#{file_keyname}.pem.pub"
211
- puts "Looking for #{public_keyfile} to verify artifact"
212
- if !File.exist? public_keyfile
213
- raise "Can't find #{public_keyfile}"
214
- end
215
-
216
- raise 'Invalid artifact digest algorithm detected' if !VALID_PROFILE_DIGESTS.member?(file_alg)
217
- raise 'Invalid artifact version detected' if !VALID_PROFILE_VERSIONS.member?(file_version)
218
- end
219
-
220
- def verify(file_to_verifiy, &content_block)
221
- f = File.open(file_to_verifiy, 'r')
222
- file_version = f.readline.strip!
223
- file_keyname = f.readline.strip!
224
- file_alg = f.readline.strip!
225
-
226
- file_sig = ''
227
- # the signature is multi-line
228
- while (line = f.readline) != "\n"
229
- file_sig += line
230
- end
231
- file_sig.strip!
232
- f.close
233
-
234
- valid_header?(file_alg, file_version, file_keyname)
235
-
236
- public_keyfile = "#{file_keyname}.pem.pub"
237
- verification_key = KEY_ALG.new File.read public_keyfile
238
-
239
- f = File.open(file_to_verifiy, 'r')
240
- while f.readline != "\n" do end
241
- content = f.read
242
-
243
- signature = Base64.decode64(file_sig)
244
- digest = ARTIFACT_DIGEST.new
245
- if verification_key.verify digest, signature, content
246
- content_block.yield(content)
247
- else
248
- puts 'Artifact is invalid'
249
- end
250
- end
251
-
252
- def profile_verify
253
- file_to_verifiy = options['infile']
254
- puts "Verifying #{file_to_verifiy}"
255
- verify(file_to_verifiy) do ||
256
- puts 'Artifact is valid'
257
- end
258
- end
259
-
260
- def profile_install
261
- puts 'Installing profile'
262
- file_to_verifiy = options['infile']
263
- dest_dir = options['destdir']
264
- verify(file_to_verifiy) do |content|
265
- Dir.mktmpdir do |workdir|
266
- tmpfile = Pathname.new(workdir).join('artifact_to_install.tar.gz')
267
- File.write(tmpfile, content)
268
- puts "Installing to #{dest_dir}"
269
- `tar xzf #{tmpfile} -C #{dest_dir}`
270
- end
271
- end
272
- end
273
- end
274
-
275
- # register the subcommand to Inspec CLI registry
276
- Inspec::Plugins::CLI.add_subcommand(Artifact::CLI, 'artifact', 'artifact SUBCOMMAND ...', 'Sign, verify and install artifacts', {})
277
- end
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'
83
+ INSPEC_REPORT_VERSION_1='INSPEC-REPORT-1'
84
+
85
+ ARTIFACT_DIGEST=OpenSSL::Digest::SHA512
86
+ ARTIFACT_DIGEST_NAME='SHA512'
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'
92
+ SIGNED_REPORT_SUFFIX='iar'
93
+ class CLI < Inspec::BaseCLI
94
+ namespace 'artifact'
95
+
96
+ # TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
97
+ def self.banner(command, _namespace = nil, _subcommand = false)
98
+ "#{basename} #{subcommand_prefix} #{command.usage}"
99
+ end
100
+
101
+ def self.subcommand_prefix
102
+ namespace
103
+ end
104
+
105
+ desc 'generate', 'Generate a RSA key pair for signing and verification'
106
+ option :keyname, type: :string, required: true,
107
+ desc: 'Desriptive name of key'
108
+ option :keydir, type: :string, default: './',
109
+ desc: 'Directory to search for keys'
110
+ def generate_keys
111
+ puts 'Generating keys'
112
+ keygen
113
+ end
114
+
115
+ desc 'sign-profile', 'Create a signed .iaf artifact'
116
+ option :profile, type: :string, required: true,
117
+ desc: 'Path to profile directory'
118
+ option :keyname, type: :string, required: true,
119
+ desc: 'Desriptive name of key'
120
+ def sign_profile
121
+ profile_sign
122
+ end
123
+
124
+ desc 'verify-profile', 'Verify a signed .iaf artifact'
125
+ option :infile, type: :string, required: true,
126
+ desc: '.iaf file to verify'
127
+ def verify_profile
128
+ profile_verify
129
+ end
130
+
131
+ desc 'install-profile', 'Verify and install a signed .iaf artifact'
132
+ option :infile, type: :string, required: true,
133
+ desc: '.iaf file to install'
134
+ option :destdir, type: :string, required: true,
135
+ desc: 'Installation directory'
136
+ def install_profile
137
+ profile_install
138
+ end
139
+
140
+ private
141
+
142
+ def keygen
143
+ key = KEY_ALG.new KEY_BITS
144
+ puts 'Generating private key'
145
+ open "#{options['keyname']}.pem.key", 'w' do |io| io.write key.to_pem end
146
+ puts 'Generating public key'
147
+ open "#{options['keyname']}.pem.pub", 'w' do |io| io.write key.public_key.to_pem end
148
+ end
149
+
150
+ def read_profile_metadata(path_to_profile)
151
+ begin
152
+ p = Pathname.new(path_to_profile)
153
+ p = p.join('inspec.yml')
154
+ if not p.exist?
155
+ raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
156
+ end
157
+ yaml = YAML.load_file(p.to_s)
158
+ yaml = yaml.to_hash
159
+
160
+ if not yaml.key? 'name'
161
+ raise 'Profile is invalid, name is not defined'
162
+ end
163
+
164
+ if not yaml.key? 'version'
165
+ raise 'Profile is invalid, version is not defined'
166
+ end
167
+ rescue => e
168
+ # rewrap it and pass it up to the CLI
169
+ raise "Error reading Inspec profile metadata: #{e}"
170
+ end
171
+
172
+ yaml
173
+ end
174
+
175
+ def profile_compress(path_to_profile, profile_md, workdir)
176
+ profile_name = profile_md['name']
177
+ profile_version = profile_md['version']
178
+ outfile_name = "#{workdir}/#{profile_name}-#{profile_version}.tar.gz"
179
+ `tar czf #{outfile_name} -C #{path_to_profile} .`
180
+ outfile_name
181
+ end
182
+
183
+ def profile_sign
184
+ Dir.mktmpdir do |workdir|
185
+ puts "Signing #{options['profile']} with key #{options['keyname']}"
186
+ path_to_profile = options['profile']
187
+ profile_md = read_profile_metadata(path_to_profile)
188
+ artifact_filename = "#{profile_md['name']}-#{profile_md['version']}.#{SIGNED_PROFILE_SUFFIX}"
189
+ tarfile = profile_compress(path_to_profile, profile_md, workdir)
190
+ content = IO.binread(tarfile)
191
+ signing_key = KEY_ALG.new File.read "#{options['keyname']}.pem.key"
192
+ sha = ARTIFACT_DIGEST.new
193
+ signature = signing_key.sign sha, content
194
+ # convert the signature to Base64
195
+ signature_base64 = Base64.encode64(signature)
196
+ tar_content = IO.binread(tarfile)
197
+ File.open(artifact_filename, 'wb') do |f|
198
+ f.puts(INSPEC_PROFILE_VERSION_1)
199
+ f.puts(options['keyname'])
200
+ f.puts(ARTIFACT_DIGEST_NAME)
201
+ f.puts(signature_base64)
202
+ f.puts('') # newline separates artifact header with body
203
+ f.write(tar_content)
204
+ end
205
+ puts "Successfully generated #{artifact_filename}"
206
+ end
207
+ end
208
+
209
+ def valid_header?(file_alg, file_version, file_keyname)
210
+ public_keyfile = "#{file_keyname}.pem.pub"
211
+ puts "Looking for #{public_keyfile} to verify artifact"
212
+ if !File.exist? public_keyfile
213
+ raise "Can't find #{public_keyfile}"
214
+ end
215
+
216
+ raise 'Invalid artifact digest algorithm detected' if !VALID_PROFILE_DIGESTS.member?(file_alg)
217
+ raise 'Invalid artifact version detected' if !VALID_PROFILE_VERSIONS.member?(file_version)
218
+ end
219
+
220
+ def verify(file_to_verifiy, &content_block)
221
+ f = File.open(file_to_verifiy, 'r')
222
+ file_version = f.readline.strip!
223
+ file_keyname = f.readline.strip!
224
+ file_alg = f.readline.strip!
225
+
226
+ file_sig = ''
227
+ # the signature is multi-line
228
+ while (line = f.readline) != "\n"
229
+ file_sig += line
230
+ end
231
+ file_sig.strip!
232
+ f.close
233
+
234
+ valid_header?(file_alg, file_version, file_keyname)
235
+
236
+ public_keyfile = "#{file_keyname}.pem.pub"
237
+ verification_key = KEY_ALG.new File.read public_keyfile
238
+
239
+ f = File.open(file_to_verifiy, 'r')
240
+ while f.readline != "\n" do end
241
+ content = f.read
242
+
243
+ signature = Base64.decode64(file_sig)
244
+ digest = ARTIFACT_DIGEST.new
245
+ if verification_key.verify digest, signature, content
246
+ content_block.yield(content)
247
+ else
248
+ puts 'Artifact is invalid'
249
+ end
250
+ end
251
+
252
+ def profile_verify
253
+ file_to_verifiy = options['infile']
254
+ puts "Verifying #{file_to_verifiy}"
255
+ verify(file_to_verifiy) do ||
256
+ puts 'Artifact is valid'
257
+ end
258
+ end
259
+
260
+ def profile_install
261
+ puts 'Installing profile'
262
+ file_to_verifiy = options['infile']
263
+ dest_dir = options['destdir']
264
+ verify(file_to_verifiy) do |content|
265
+ Dir.mktmpdir do |workdir|
266
+ tmpfile = Pathname.new(workdir).join('artifact_to_install.tar.gz')
267
+ File.write(tmpfile, content)
268
+ puts "Installing to #{dest_dir}"
269
+ `tar xzf #{tmpfile} -C #{dest_dir}`
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ # register the subcommand to Inspec CLI registry
276
+ Inspec::Plugins::CLI.add_subcommand(Artifact::CLI, 'artifact', 'artifact SUBCOMMAND ...', 'Sign, verify and install artifacts', {})
277
+ end