inspec 2.1.0 → 2.1.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (489) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +101 -101
  3. data/CHANGELOG.md +3024 -3004
  4. data/Gemfile +55 -55
  5. data/LICENSE +14 -14
  6. data/MAINTAINERS.md +33 -33
  7. data/MAINTAINERS.toml +52 -52
  8. data/README.md +447 -446
  9. data/Rakefile +322 -322
  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 +100 -93
  15. data/docs/glossary.md +99 -99
  16. data/docs/habitat.md +191 -191
  17. data/docs/inspec_and_friends.md +114 -114
  18. data/docs/matchers.md +169 -169
  19. data/docs/migration.md +293 -293
  20. data/docs/platforms.md +118 -118
  21. data/docs/plugin_kitchen_inspec.md +50 -50
  22. data/docs/profiles.md +376 -376
  23. data/docs/reporters.md +105 -105
  24. data/docs/resources/aide_conf.md.erb +75 -75
  25. data/docs/resources/apache.md.erb +67 -67
  26. data/docs/resources/apache_conf.md.erb +68 -68
  27. data/docs/resources/apt.md.erb +71 -71
  28. data/docs/resources/audit_policy.md.erb +47 -47
  29. data/docs/resources/auditd.md.erb +79 -79
  30. data/docs/resources/auditd_conf.md.erb +68 -68
  31. data/docs/resources/aws_cloudtrail_trail.md.erb +140 -140
  32. data/docs/resources/aws_cloudtrail_trails.md.erb +81 -81
  33. data/docs/resources/aws_cloudwatch_alarm.md.erb +86 -86
  34. data/docs/resources/aws_cloudwatch_log_metric_filter.md.erb +151 -151
  35. data/docs/resources/aws_config_recorder.md.erb +71 -71
  36. data/docs/resources/aws_ec2_instance.md.erb +106 -106
  37. data/docs/resources/aws_iam_access_key.md.erb +123 -123
  38. data/docs/resources/aws_iam_access_keys.md.erb +198 -198
  39. data/docs/resources/aws_iam_group.md.erb +46 -46
  40. data/docs/resources/aws_iam_groups.md.erb +43 -43
  41. data/docs/resources/aws_iam_password_policy.md.erb +76 -76
  42. data/docs/resources/aws_iam_policies.md.erb +82 -82
  43. data/docs/resources/aws_iam_policy.md.erb +144 -144
  44. data/docs/resources/aws_iam_role.md.erb +63 -63
  45. data/docs/resources/aws_iam_root_user.md.erb +58 -58
  46. data/docs/resources/aws_iam_user.md.erb +64 -64
  47. data/docs/resources/aws_iam_users.md.erb +89 -89
  48. data/docs/resources/aws_kms_keys.md.erb +84 -84
  49. data/docs/resources/aws_route_table.md.erb +47 -47
  50. data/docs/resources/aws_s3_bucket.md.erb +134 -134
  51. data/docs/resources/aws_s3_bucket_object.md.erb +83 -0
  52. data/docs/resources/aws_security_group.md.erb +151 -151
  53. data/docs/resources/aws_security_groups.md.erb +91 -91
  54. data/docs/resources/aws_sns_subscription.md.erb +125 -0
  55. data/docs/resources/aws_sns_topic.md.erb +63 -63
  56. data/docs/resources/aws_sns_topics.md.erb +52 -0
  57. data/docs/resources/aws_subnet.md.erb +134 -134
  58. data/docs/resources/aws_subnets.md.erb +126 -126
  59. data/docs/resources/aws_vpc.md.erb +120 -120
  60. data/docs/resources/aws_vpcs.md.erb +48 -48
  61. data/docs/resources/azure_generic_resource.md.erb +171 -171
  62. data/docs/resources/azure_resource_group.md.erb +284 -284
  63. data/docs/resources/azure_virtual_machine.md.erb +347 -347
  64. data/docs/resources/azure_virtual_machine_data_disk.md.erb +224 -224
  65. data/docs/resources/bash.md.erb +75 -75
  66. data/docs/resources/bond.md.erb +90 -90
  67. data/docs/resources/bridge.md.erb +57 -57
  68. data/docs/resources/bsd_service.md.erb +67 -67
  69. data/docs/resources/command.md.erb +138 -138
  70. data/docs/resources/cpan.md.erb +79 -79
  71. data/docs/resources/cran.md.erb +64 -64
  72. data/docs/resources/crontab.md.erb +89 -89
  73. data/docs/resources/csv.md.erb +54 -54
  74. data/docs/resources/dh_params.md.erb +205 -205
  75. data/docs/resources/directory.md.erb +30 -30
  76. data/docs/resources/docker.md.erb +219 -219
  77. data/docs/resources/docker_container.md.erb +103 -103
  78. data/docs/resources/docker_image.md.erb +94 -94
  79. data/docs/resources/docker_service.md.erb +114 -114
  80. data/docs/resources/elasticsearch.md.erb +242 -242
  81. data/docs/resources/etc_fstab.md.erb +125 -125
  82. data/docs/resources/etc_group.md.erb +75 -75
  83. data/docs/resources/etc_hosts.md.erb +78 -78
  84. data/docs/resources/etc_hosts_allow.md.erb +74 -74
  85. data/docs/resources/etc_hosts_deny.md.erb +74 -74
  86. data/docs/resources/file.md.erb +526 -526
  87. data/docs/resources/filesystem.md.erb +41 -41
  88. data/docs/resources/firewalld.md.erb +107 -107
  89. data/docs/resources/gem.md.erb +79 -79
  90. data/docs/resources/group.md.erb +61 -61
  91. data/docs/resources/grub_conf.md.erb +101 -101
  92. data/docs/resources/host.md.erb +86 -86
  93. data/docs/resources/http.md.erb +196 -196
  94. data/docs/resources/iis_app.md.erb +122 -122
  95. data/docs/resources/iis_site.md.erb +135 -135
  96. data/docs/resources/inetd_conf.md.erb +94 -94
  97. data/docs/resources/ini.md.erb +76 -76
  98. data/docs/resources/interface.md.erb +58 -58
  99. data/docs/resources/iptables.md.erb +64 -64
  100. data/docs/resources/json.md.erb +63 -63
  101. data/docs/resources/kernel_module.md.erb +120 -120
  102. data/docs/resources/kernel_parameter.md.erb +53 -53
  103. data/docs/resources/key_rsa.md.erb +85 -85
  104. data/docs/resources/launchd_service.md.erb +57 -57
  105. data/docs/resources/limits_conf.md.erb +75 -75
  106. data/docs/resources/{login_def.md.erb → login_defs.md.erb} +71 -71
  107. data/docs/resources/mount.md.erb +69 -69
  108. data/docs/resources/mssql_session.md.erb +60 -60
  109. data/docs/resources/mysql_conf.md.erb +99 -99
  110. data/docs/resources/mysql_session.md.erb +74 -74
  111. data/docs/resources/nginx.md.erb +79 -79
  112. data/docs/resources/nginx_conf.md.erb +138 -128
  113. data/docs/resources/npm.md.erb +60 -60
  114. data/docs/resources/ntp_conf.md.erb +60 -60
  115. data/docs/resources/oneget.md.erb +53 -53
  116. data/docs/resources/oracledb_session.md.erb +52 -52
  117. data/docs/resources/os.md.erb +141 -141
  118. data/docs/resources/os_env.md.erb +78 -78
  119. data/docs/resources/package.md.erb +120 -120
  120. data/docs/resources/packages.md.erb +67 -67
  121. data/docs/resources/parse_config.md.erb +103 -103
  122. data/docs/resources/parse_config_file.md.erb +138 -138
  123. data/docs/resources/passwd.md.erb +141 -141
  124. data/docs/resources/pip.md.erb +67 -67
  125. data/docs/resources/port.md.erb +137 -137
  126. data/docs/resources/postgres_conf.md.erb +79 -79
  127. data/docs/resources/postgres_hba_conf.md.erb +93 -93
  128. data/docs/resources/postgres_ident_conf.md.erb +76 -76
  129. data/docs/resources/postgres_session.md.erb +69 -69
  130. data/docs/resources/powershell.md.erb +102 -102
  131. data/docs/resources/processes.md.erb +109 -109
  132. data/docs/resources/rabbitmq_config.md.erb +41 -41
  133. data/docs/resources/registry_key.md.erb +158 -158
  134. data/docs/resources/runit_service.md.erb +57 -57
  135. data/docs/resources/security_policy.md.erb +47 -47
  136. data/docs/resources/service.md.erb +121 -121
  137. data/docs/resources/shadow.md.erb +146 -146
  138. data/docs/resources/ssh_config.md.erb +73 -80
  139. data/docs/resources/sshd_config.md.erb +83 -83
  140. data/docs/resources/ssl.md.erb +119 -119
  141. data/docs/resources/sys_info.md.erb +42 -42
  142. data/docs/resources/systemd_service.md.erb +57 -57
  143. data/docs/resources/sysv_service.md.erb +57 -57
  144. data/docs/resources/upstart_service.md.erb +57 -57
  145. data/docs/resources/user.md.erb +140 -140
  146. data/docs/resources/users.md.erb +127 -127
  147. data/docs/resources/vbscript.md.erb +55 -55
  148. data/docs/resources/virtualization.md.erb +57 -57
  149. data/docs/resources/windows_feature.md.erb +47 -47
  150. data/docs/resources/windows_hotfix.md.erb +53 -53
  151. data/docs/resources/windows_task.md.erb +95 -95
  152. data/docs/resources/wmi.md.erb +81 -81
  153. data/docs/resources/x509_certificate.md.erb +151 -151
  154. data/docs/resources/xinetd_conf.md.erb +156 -156
  155. data/docs/resources/xml.md.erb +85 -85
  156. data/docs/resources/yaml.md.erb +69 -69
  157. data/docs/resources/yum.md.erb +98 -98
  158. data/docs/resources/zfs_dataset.md.erb +53 -53
  159. data/docs/resources/zfs_pool.md.erb +47 -47
  160. data/docs/ruby_usage.md +203 -203
  161. data/docs/shared/matcher_be.md.erb +1 -1
  162. data/docs/shared/matcher_cmp.md.erb +43 -43
  163. data/docs/shared/matcher_eq.md.erb +3 -3
  164. data/docs/shared/matcher_include.md.erb +1 -1
  165. data/docs/shared/matcher_match.md.erb +1 -1
  166. data/docs/shell.md +217 -217
  167. data/examples/README.md +8 -8
  168. data/examples/inheritance/README.md +65 -65
  169. data/examples/inheritance/controls/example.rb +14 -14
  170. data/examples/inheritance/inspec.yml +15 -15
  171. data/examples/kitchen-ansible/.kitchen.yml +25 -25
  172. data/examples/kitchen-ansible/Gemfile +19 -19
  173. data/examples/kitchen-ansible/README.md +53 -53
  174. data/examples/kitchen-ansible/files/nginx.repo +6 -6
  175. data/examples/kitchen-ansible/tasks/main.yml +16 -16
  176. data/examples/kitchen-ansible/test/integration/default/default.yml +5 -5
  177. data/examples/kitchen-ansible/test/integration/default/web_spec.rb +28 -28
  178. data/examples/kitchen-chef/.kitchen.yml +20 -20
  179. data/examples/kitchen-chef/Berksfile +3 -3
  180. data/examples/kitchen-chef/Gemfile +19 -19
  181. data/examples/kitchen-chef/README.md +27 -27
  182. data/examples/kitchen-chef/metadata.rb +7 -7
  183. data/examples/kitchen-chef/recipes/default.rb +6 -6
  184. data/examples/kitchen-chef/recipes/nginx.rb +30 -30
  185. data/examples/kitchen-chef/test/integration/default/web_spec.rb +28 -28
  186. data/examples/kitchen-puppet/.kitchen.yml +22 -22
  187. data/examples/kitchen-puppet/Gemfile +20 -20
  188. data/examples/kitchen-puppet/Puppetfile +25 -25
  189. data/examples/kitchen-puppet/README.md +53 -53
  190. data/examples/kitchen-puppet/manifests/site.pp +33 -33
  191. data/examples/kitchen-puppet/metadata.json +11 -11
  192. data/examples/kitchen-puppet/test/integration/default/web_spec.rb +28 -28
  193. data/examples/meta-profile/README.md +37 -37
  194. data/examples/meta-profile/controls/example.rb +13 -13
  195. data/examples/meta-profile/inspec.yml +13 -13
  196. data/examples/profile-attribute.yml +2 -2
  197. data/examples/profile-attribute/README.md +14 -14
  198. data/examples/profile-attribute/controls/example.rb +11 -11
  199. data/examples/profile-attribute/inspec.yml +8 -8
  200. data/examples/profile-aws/controls/iam_password_policy_expiration.rb +8 -8
  201. data/examples/profile-aws/controls/iam_password_policy_max_age.rb +8 -8
  202. data/examples/profile-aws/controls/iam_root_user_mfa.rb +8 -8
  203. data/examples/profile-aws/controls/iam_users_access_key_age.rb +8 -8
  204. data/examples/profile-aws/controls/iam_users_console_users_mfa.rb +8 -8
  205. data/examples/profile-aws/inspec.yml +11 -11
  206. data/examples/profile-azure/controls/azure_resource_group_example.rb +24 -24
  207. data/examples/profile-azure/controls/azure_vm_example.rb +29 -29
  208. data/examples/profile-azure/inspec.yml +11 -11
  209. data/examples/profile-sensitive/README.md +29 -29
  210. data/examples/profile-sensitive/controls/sensitive-failures.rb +9 -9
  211. data/examples/profile-sensitive/controls/sensitive.rb +9 -9
  212. data/examples/profile-sensitive/inspec.yml +8 -8
  213. data/examples/profile/README.md +48 -48
  214. data/examples/profile/controls/example.rb +23 -23
  215. data/examples/profile/controls/gordon.rb +36 -36
  216. data/examples/profile/controls/meta.rb +34 -34
  217. data/examples/profile/inspec.yml +10 -10
  218. data/examples/profile/libraries/gordon_config.rb +53 -53
  219. data/inspec.gemspec +47 -47
  220. data/lib/bundles/README.md +3 -3
  221. data/lib/bundles/inspec-artifact.rb +7 -7
  222. data/lib/bundles/inspec-artifact/README.md +1 -1
  223. data/lib/bundles/inspec-artifact/cli.rb +277 -277
  224. data/lib/bundles/inspec-compliance.rb +16 -16
  225. data/lib/bundles/inspec-compliance/.kitchen.yml +20 -20
  226. data/lib/bundles/inspec-compliance/README.md +185 -185
  227. data/lib/bundles/inspec-compliance/api.rb +316 -316
  228. data/lib/bundles/inspec-compliance/api/login.rb +152 -152
  229. data/lib/bundles/inspec-compliance/bootstrap.sh +41 -41
  230. data/lib/bundles/inspec-compliance/cli.rb +254 -254
  231. data/lib/bundles/inspec-compliance/configuration.rb +103 -103
  232. data/lib/bundles/inspec-compliance/http.rb +86 -86
  233. data/lib/bundles/inspec-compliance/support.rb +36 -36
  234. data/lib/bundles/inspec-compliance/target.rb +98 -98
  235. data/lib/bundles/inspec-compliance/test/integration/default/cli.rb +93 -93
  236. data/lib/bundles/inspec-habitat.rb +12 -12
  237. data/lib/bundles/inspec-habitat/cli.rb +36 -36
  238. data/lib/bundles/inspec-habitat/log.rb +10 -10
  239. data/lib/bundles/inspec-habitat/profile.rb +390 -390
  240. data/lib/bundles/inspec-init.rb +8 -8
  241. data/lib/bundles/inspec-init/README.md +31 -31
  242. data/lib/bundles/inspec-init/cli.rb +97 -97
  243. data/lib/bundles/inspec-init/templates/profile/README.md +3 -3
  244. data/lib/bundles/inspec-init/templates/profile/controls/example.rb +19 -19
  245. data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -8
  246. data/lib/bundles/inspec-supermarket.rb +13 -13
  247. data/lib/bundles/inspec-supermarket/README.md +45 -45
  248. data/lib/bundles/inspec-supermarket/api.rb +84 -84
  249. data/lib/bundles/inspec-supermarket/cli.rb +73 -73
  250. data/lib/bundles/inspec-supermarket/target.rb +34 -34
  251. data/lib/fetchers/git.rb +163 -163
  252. data/lib/fetchers/local.rb +74 -74
  253. data/lib/fetchers/mock.rb +35 -35
  254. data/lib/fetchers/url.rb +204 -204
  255. data/lib/inspec.rb +24 -24
  256. data/lib/inspec/archive/tar.rb +29 -29
  257. data/lib/inspec/archive/zip.rb +19 -19
  258. data/lib/inspec/backend.rb +93 -93
  259. data/lib/inspec/base_cli.rb +357 -355
  260. data/lib/inspec/cached_fetcher.rb +66 -66
  261. data/lib/inspec/cli.rb +292 -292
  262. data/lib/inspec/completions/bash.sh.erb +45 -45
  263. data/lib/inspec/completions/fish.sh.erb +34 -34
  264. data/lib/inspec/completions/zsh.sh.erb +61 -61
  265. data/lib/inspec/control_eval_context.rb +179 -179
  266. data/lib/inspec/dependencies/cache.rb +72 -72
  267. data/lib/inspec/dependencies/dependency_set.rb +92 -92
  268. data/lib/inspec/dependencies/lockfile.rb +115 -115
  269. data/lib/inspec/dependencies/requirement.rb +123 -123
  270. data/lib/inspec/dependencies/resolver.rb +86 -86
  271. data/lib/inspec/describe.rb +27 -27
  272. data/lib/inspec/dsl.rb +66 -66
  273. data/lib/inspec/dsl_shared.rb +33 -33
  274. data/lib/inspec/env_printer.rb +157 -157
  275. data/lib/inspec/errors.rb +13 -13
  276. data/lib/inspec/exceptions.rb +12 -12
  277. data/lib/inspec/expect.rb +45 -45
  278. data/lib/inspec/fetcher.rb +45 -45
  279. data/lib/inspec/file_provider.rb +275 -275
  280. data/lib/inspec/formatters.rb +3 -3
  281. data/lib/inspec/formatters/base.rb +250 -250
  282. data/lib/inspec/formatters/json_rspec.rb +20 -20
  283. data/lib/inspec/formatters/show_progress.rb +12 -12
  284. data/lib/inspec/library_eval_context.rb +58 -58
  285. data/lib/inspec/log.rb +11 -11
  286. data/lib/inspec/metadata.rb +247 -247
  287. data/lib/inspec/method_source.rb +24 -24
  288. data/lib/inspec/objects.rb +14 -14
  289. data/lib/inspec/objects/attribute.rb +65 -65
  290. data/lib/inspec/objects/control.rb +61 -61
  291. data/lib/inspec/objects/describe.rb +92 -92
  292. data/lib/inspec/objects/each_loop.rb +36 -36
  293. data/lib/inspec/objects/list.rb +15 -15
  294. data/lib/inspec/objects/or_test.rb +40 -40
  295. data/lib/inspec/objects/ruby_helper.rb +15 -15
  296. data/lib/inspec/objects/tag.rb +27 -27
  297. data/lib/inspec/objects/test.rb +87 -87
  298. data/lib/inspec/objects/value.rb +27 -27
  299. data/lib/inspec/plugins.rb +60 -60
  300. data/lib/inspec/plugins/cli.rb +24 -24
  301. data/lib/inspec/plugins/fetcher.rb +86 -86
  302. data/lib/inspec/plugins/resource.rb +135 -135
  303. data/lib/inspec/plugins/secret.rb +15 -15
  304. data/lib/inspec/plugins/source_reader.rb +40 -40
  305. data/lib/inspec/polyfill.rb +12 -12
  306. data/lib/inspec/profile.rb +510 -510
  307. data/lib/inspec/profile_context.rb +207 -207
  308. data/lib/inspec/profile_vendor.rb +66 -66
  309. data/lib/inspec/reporters.rb +54 -54
  310. data/lib/inspec/reporters/base.rb +24 -24
  311. data/lib/inspec/reporters/cli.rb +356 -356
  312. data/lib/inspec/reporters/json.rb +116 -116
  313. data/lib/inspec/reporters/json_min.rb +48 -48
  314. data/lib/inspec/reporters/junit.rb +77 -77
  315. data/lib/inspec/require_loader.rb +33 -33
  316. data/lib/inspec/resource.rb +186 -186
  317. data/lib/inspec/rule.rb +266 -266
  318. data/lib/inspec/runner.rb +345 -345
  319. data/lib/inspec/runner_mock.rb +41 -41
  320. data/lib/inspec/runner_rspec.rb +175 -175
  321. data/lib/inspec/runtime_profile.rb +26 -26
  322. data/lib/inspec/schema.rb +213 -213
  323. data/lib/inspec/secrets.rb +19 -19
  324. data/lib/inspec/secrets/yaml.rb +30 -30
  325. data/lib/inspec/shell.rb +220 -220
  326. data/lib/inspec/shell_detector.rb +90 -90
  327. data/lib/inspec/source_reader.rb +29 -29
  328. data/lib/inspec/version.rb +8 -8
  329. data/lib/matchers/matchers.rb +339 -339
  330. data/lib/resource_support/aws.rb +44 -41
  331. data/lib/resource_support/aws/aws_backend_base.rb +12 -12
  332. data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -12
  333. data/lib/resource_support/aws/aws_plural_resource_mixin.rb +21 -21
  334. data/lib/resource_support/aws/aws_resource_mixin.rb +66 -66
  335. data/lib/resource_support/aws/aws_singular_resource_mixin.rb +24 -24
  336. data/lib/resources/aide_conf.rb +151 -159
  337. data/lib/resources/apache.rb +48 -48
  338. data/lib/resources/apache_conf.rb +149 -156
  339. data/lib/resources/apt.rb +149 -149
  340. data/lib/resources/audit_policy.rb +63 -63
  341. data/lib/resources/auditd.rb +231 -231
  342. data/lib/resources/auditd_conf.rb +46 -55
  343. data/lib/resources/aws/aws_cloudtrail_trail.rb +77 -77
  344. data/lib/resources/aws/aws_cloudtrail_trails.rb +47 -47
  345. data/lib/resources/aws/aws_cloudwatch_alarm.rb +62 -62
  346. data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +100 -100
  347. data/lib/resources/aws/aws_config_recorder.rb +98 -98
  348. data/lib/resources/aws/aws_ec2_instance.rb +157 -157
  349. data/lib/resources/aws/aws_iam_access_key.rb +106 -106
  350. data/lib/resources/aws/aws_iam_access_keys.rb +149 -149
  351. data/lib/resources/aws/aws_iam_group.rb +56 -56
  352. data/lib/resources/aws/aws_iam_groups.rb +52 -52
  353. data/lib/resources/aws/aws_iam_password_policy.rb +116 -116
  354. data/lib/resources/aws/aws_iam_policies.rb +53 -53
  355. data/lib/resources/aws/aws_iam_policy.rb +125 -125
  356. data/lib/resources/aws/aws_iam_role.rb +51 -51
  357. data/lib/resources/aws/aws_iam_root_user.rb +60 -60
  358. data/lib/resources/aws/aws_iam_user.rb +111 -111
  359. data/lib/resources/aws/aws_iam_users.rb +108 -108
  360. data/lib/resources/aws/aws_kms_keys.rb +53 -53
  361. data/lib/resources/aws/aws_route_table.rb +61 -61
  362. data/lib/resources/aws/aws_s3_bucket.rb +115 -115
  363. data/lib/resources/aws/aws_s3_bucket_object.rb +82 -0
  364. data/lib/resources/aws/aws_security_group.rb +93 -93
  365. data/lib/resources/aws/aws_security_groups.rb +68 -68
  366. data/lib/resources/aws/aws_sns_subscription.rb +78 -0
  367. data/lib/resources/aws/aws_sns_topic.rb +53 -53
  368. data/lib/resources/aws/aws_sns_topics.rb +56 -0
  369. data/lib/resources/aws/aws_subnet.rb +88 -88
  370. data/lib/resources/aws/aws_subnets.rb +53 -53
  371. data/lib/resources/aws/aws_vpc.rb +69 -69
  372. data/lib/resources/aws/aws_vpcs.rb +45 -45
  373. data/lib/resources/azure/azure_backend.rb +377 -377
  374. data/lib/resources/azure/azure_generic_resource.rb +59 -59
  375. data/lib/resources/azure/azure_resource_group.rb +152 -152
  376. data/lib/resources/azure/azure_virtual_machine.rb +264 -264
  377. data/lib/resources/azure/azure_virtual_machine_data_disk.rb +136 -136
  378. data/lib/resources/bash.rb +35 -35
  379. data/lib/resources/bond.rb +69 -68
  380. data/lib/resources/bridge.rb +122 -122
  381. data/lib/resources/command.rb +73 -73
  382. data/lib/resources/cpan.rb +58 -58
  383. data/lib/resources/cran.rb +64 -64
  384. data/lib/resources/crontab.rb +169 -169
  385. data/lib/resources/csv.rb +56 -60
  386. data/lib/resources/dh_params.rb +77 -82
  387. data/lib/resources/directory.rb +25 -25
  388. data/lib/resources/docker.rb +236 -236
  389. data/lib/resources/docker_container.rb +89 -89
  390. data/lib/resources/docker_image.rb +83 -83
  391. data/lib/resources/docker_object.rb +57 -57
  392. data/lib/resources/docker_service.rb +90 -90
  393. data/lib/resources/elasticsearch.rb +169 -169
  394. data/lib/resources/etc_fstab.rb +94 -101
  395. data/lib/resources/etc_group.rb +152 -152
  396. data/lib/resources/etc_hosts.rb +66 -82
  397. data/lib/resources/etc_hosts_allow_deny.rb +112 -122
  398. data/lib/resources/file.rb +298 -298
  399. data/lib/resources/filesystem.rb +31 -31
  400. data/lib/resources/firewalld.rb +143 -143
  401. data/lib/resources/gem.rb +70 -70
  402. data/lib/resources/groups.rb +215 -215
  403. data/lib/resources/grub_conf.rb +227 -237
  404. data/lib/resources/host.rb +306 -306
  405. data/lib/resources/http.rb +251 -251
  406. data/lib/resources/iis_app.rb +101 -101
  407. data/lib/resources/iis_site.rb +148 -148
  408. data/lib/resources/inetd_conf.rb +54 -62
  409. data/lib/resources/ini.rb +29 -29
  410. data/lib/resources/interface.rb +129 -129
  411. data/lib/resources/iptables.rb +80 -80
  412. data/lib/resources/json.rb +107 -117
  413. data/lib/resources/kernel_module.rb +107 -107
  414. data/lib/resources/kernel_parameter.rb +58 -58
  415. data/lib/resources/key_rsa.rb +61 -67
  416. data/lib/resources/limits_conf.rb +46 -55
  417. data/lib/resources/login_def.rb +57 -66
  418. data/lib/resources/mount.rb +88 -88
  419. data/lib/resources/mssql_session.rb +101 -101
  420. data/lib/resources/mysql.rb +81 -81
  421. data/lib/resources/mysql_conf.rb +127 -134
  422. data/lib/resources/mysql_session.rb +85 -85
  423. data/lib/resources/nginx.rb +96 -96
  424. data/lib/resources/nginx_conf.rb +226 -227
  425. data/lib/resources/npm.rb +48 -48
  426. data/lib/resources/ntp_conf.rb +51 -58
  427. data/lib/resources/oneget.rb +71 -71
  428. data/lib/resources/oracledb_session.rb +139 -139
  429. data/lib/resources/os.rb +36 -36
  430. data/lib/resources/os_env.rb +76 -76
  431. data/lib/resources/package.rb +370 -370
  432. data/lib/resources/packages.rb +111 -111
  433. data/lib/resources/parse_config.rb +112 -116
  434. data/lib/resources/passwd.rb +76 -74
  435. data/lib/resources/pip.rb +89 -89
  436. data/lib/resources/platform.rb +109 -109
  437. data/lib/resources/port.rb +771 -771
  438. data/lib/resources/postgres.rb +130 -130
  439. data/lib/resources/postgres_conf.rb +114 -121
  440. data/lib/resources/postgres_hba_conf.rb +90 -99
  441. data/lib/resources/postgres_ident_conf.rb +79 -76
  442. data/lib/resources/postgres_session.rb +71 -71
  443. data/lib/resources/powershell.rb +53 -53
  444. data/lib/resources/processes.rb +204 -204
  445. data/lib/resources/rabbitmq_conf.rb +51 -52
  446. data/lib/resources/registry_key.rb +296 -296
  447. data/lib/resources/security_policy.rb +180 -180
  448. data/lib/resources/service.rb +790 -789
  449. data/lib/resources/shadow.rb +149 -146
  450. data/lib/resources/ssh_conf.rb +97 -102
  451. data/lib/resources/ssl.rb +99 -99
  452. data/lib/resources/sys_info.rb +28 -28
  453. data/lib/resources/toml.rb +32 -32
  454. data/lib/resources/users.rb +654 -654
  455. data/lib/resources/vbscript.rb +68 -68
  456. data/lib/resources/virtualization.rb +247 -247
  457. data/lib/resources/windows_feature.rb +84 -84
  458. data/lib/resources/windows_hotfix.rb +35 -35
  459. data/lib/resources/windows_task.rb +102 -102
  460. data/lib/resources/wmi.rb +110 -110
  461. data/lib/resources/x509_certificate.rb +137 -143
  462. data/lib/resources/xinetd.rb +106 -111
  463. data/lib/resources/xml.rb +46 -46
  464. data/lib/resources/yaml.rb +43 -47
  465. data/lib/resources/yum.rb +180 -180
  466. data/lib/resources/zfs_dataset.rb +60 -60
  467. data/lib/resources/zfs_pool.rb +49 -49
  468. data/lib/source_readers/flat.rb +39 -39
  469. data/lib/source_readers/inspec.rb +75 -75
  470. data/lib/utils/command_wrapper.rb +27 -27
  471. data/lib/utils/convert.rb +12 -12
  472. data/lib/utils/database_helpers.rb +77 -77
  473. data/lib/utils/erlang_parser.rb +192 -192
  474. data/lib/utils/file_reader.rb +25 -0
  475. data/lib/utils/filter.rb +272 -272
  476. data/lib/utils/filter_array.rb +27 -27
  477. data/lib/utils/find_files.rb +44 -44
  478. data/lib/utils/hash.rb +41 -41
  479. data/lib/utils/json_log.rb +18 -18
  480. data/lib/utils/latest_version.rb +22 -22
  481. data/lib/utils/modulator.rb +12 -12
  482. data/lib/utils/nginx_parser.rb +85 -85
  483. data/lib/utils/object_traversal.rb +49 -49
  484. data/lib/utils/parser.rb +274 -274
  485. data/lib/utils/plugin_registry.rb +93 -93
  486. data/lib/utils/simpleconfig.rb +120 -120
  487. data/lib/utils/spdx.rb +13 -13
  488. data/lib/utils/spdx.txt +343 -343
  489. metadata +12 -5
@@ -1,23 +1,23 @@
1
- # encoding: utf-8
2
- # copyright: 2015, Chef Software, Inc.
3
-
4
- title '/tmp profile'
5
-
6
- # you add controls here
7
- control "tmp-1.0" do # A unique ID for this control
8
- impact 0.7 # The criticality, if this control fails.
9
- title "Create /tmp directory" # A human-readable title
10
- desc "An optional description..." # Describe why this is needed
11
- tag data: "temp data" # A tag allows you to associate key information
12
- tag "security" # to the test
13
- ref "Document A-12", url: 'http://...' # Additional references
14
-
15
- describe file('/tmp') do # The actual test
16
- it { should be_directory }
17
- end
18
- end
19
-
20
- # you can also use plain tests
21
- describe file('/tmp') do
22
- it { should be_directory }
23
- end
1
+ # encoding: utf-8
2
+ # copyright: 2015, Chef Software, Inc.
3
+
4
+ title '/tmp profile'
5
+
6
+ # you add controls here
7
+ control "tmp-1.0" do # A unique ID for this control
8
+ impact 0.7 # The criticality, if this control fails.
9
+ title "Create /tmp directory" # A human-readable title
10
+ desc "An optional description..." # Describe why this is needed
11
+ tag data: "temp data" # A tag allows you to associate key information
12
+ tag "security" # to the test
13
+ ref "Document A-12", url: 'http://...' # Additional references
14
+
15
+ describe file('/tmp') do # The actual test
16
+ it { should be_directory }
17
+ end
18
+ end
19
+
20
+ # you can also use plain tests
21
+ describe file('/tmp') do
22
+ it { should be_directory }
23
+ end
@@ -1,36 +1,36 @@
1
- # encoding: utf-8
2
- # copyright: 2016, Chef Software, Inc.
3
-
4
- title 'Gordon Config Checks'
5
-
6
- # To pass the test, create the following file
7
- # ```bash
8
- # mkdir -p /tmp/gordon
9
- # cat <<EOF > /tmp/gordon/config.yaml
10
- # version: '1.0'
11
- # EOF
12
- # ```
13
- control 'gordon-1.0' do
14
- impact 0.7
15
- title 'Verify the version number of Gordon'
16
- desc 'An optional description...'
17
- tag 'gordon'
18
- ref 'Gordon Requirements 1.0', uri: 'http://...'
19
-
20
- # Test using the custom gordon_config Inspec resource
21
- # Find the resource content here: ../libraries/
22
- describe gordon_config do
23
- it { should exist }
24
- its('version') { should eq('1.0') }
25
- its('file_size') { should <= 20 }
26
- its('comma_count') { should eq 0 }
27
- end
28
-
29
- # Test the version again to showcase variables
30
- g = gordon_config
31
- g_path = g.file_path
32
- g_version = g.version
33
- describe file(g_path) do
34
- its('content') { should match g_version }
35
- end
36
- end
1
+ # encoding: utf-8
2
+ # copyright: 2016, Chef Software, Inc.
3
+
4
+ title 'Gordon Config Checks'
5
+
6
+ # To pass the test, create the following file
7
+ # ```bash
8
+ # mkdir -p /tmp/gordon
9
+ # cat <<EOF > /tmp/gordon/config.yaml
10
+ # version: '1.0'
11
+ # EOF
12
+ # ```
13
+ control 'gordon-1.0' do
14
+ impact 0.7
15
+ title 'Verify the version number of Gordon'
16
+ desc 'An optional description...'
17
+ tag 'gordon'
18
+ ref 'Gordon Requirements 1.0', uri: 'http://...'
19
+
20
+ # Test using the custom gordon_config Inspec resource
21
+ # Find the resource content here: ../libraries/
22
+ describe gordon_config do
23
+ it { should exist }
24
+ its('version') { should eq('1.0') }
25
+ its('file_size') { should <= 20 }
26
+ its('comma_count') { should eq 0 }
27
+ end
28
+
29
+ # Test the version again to showcase variables
30
+ g = gordon_config
31
+ g_path = g.file_path
32
+ g_version = g.version
33
+ describe file(g_path) do
34
+ its('content') { should match g_version }
35
+ end
36
+ end
@@ -1,34 +1,34 @@
1
- title 'SSH Server Configuration'
2
-
3
- control 'ssh-1' do
4
- impact 1.0
5
-
6
- title 'Allow only SSH Protocol 2'
7
- desc 'Only SSH protocol version 2 connections should be permitted.
8
- The default setting in /etc/ssh/sshd_config is correct, and can be
9
- verified by ensuring that the following line appears: Protocol 2'
10
-
11
- tag 'production','development'
12
- tag 'ssh','sshd','openssh-server'
13
-
14
- tag cce: 'CCE-27072-8'
15
- tag disa: 'RHEL-06-000227'
16
-
17
- tag nist: 'AC-3(10).i'
18
- tag nist: 'IA-5(1)'
19
-
20
- tag cci: 'CCI-000776'
21
- tag cci: 'CCI-000774'
22
- tag cci: 'CCI-001436'
23
-
24
- tag remediation: 'stig_rhel6/recipes/sshd-config.rb'
25
- tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening'
26
-
27
- ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
28
- ref 'DISA-RHEL6-SG - Section 9.2.1', url: 'http://iasecontent.disa.mil/stigs/zip/Jan2016/U_RedHat_6_V1R10_STIG.zip'
29
- ref 'http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html'
30
-
31
- describe file('/bin/sh') do
32
- it { should be_owned_by 'root' }
33
- end
34
- end
1
+ title 'SSH Server Configuration'
2
+
3
+ control 'ssh-1' do
4
+ impact 1.0
5
+
6
+ title 'Allow only SSH Protocol 2'
7
+ desc 'Only SSH protocol version 2 connections should be permitted.
8
+ The default setting in /etc/ssh/sshd_config is correct, and can be
9
+ verified by ensuring that the following line appears: Protocol 2'
10
+
11
+ tag 'production','development'
12
+ tag 'ssh','sshd','openssh-server'
13
+
14
+ tag cce: 'CCE-27072-8'
15
+ tag disa: 'RHEL-06-000227'
16
+
17
+ tag nist: 'AC-3(10).i'
18
+ tag nist: 'IA-5(1)'
19
+
20
+ tag cci: 'CCI-000776'
21
+ tag cci: 'CCI-000774'
22
+ tag cci: 'CCI-001436'
23
+
24
+ tag remediation: 'stig_rhel6/recipes/sshd-config.rb'
25
+ tag remediation: 'https://supermarket.chef.io/cookbooks/ssh-hardening'
26
+
27
+ ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
28
+ ref 'DISA-RHEL6-SG - Section 9.2.1', url: 'http://iasecontent.disa.mil/stigs/zip/Jan2016/U_RedHat_6_V1R10_STIG.zip'
29
+ ref 'http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html'
30
+
31
+ describe file('/bin/sh') do
32
+ it { should be_owned_by 'root' }
33
+ end
34
+ end
@@ -1,10 +1,10 @@
1
- name: profile
2
- title: InSpec Example Profile
3
- maintainer: Chef Software, Inc.
4
- copyright: Chef Software, Inc.
5
- copyright_email: support@chef.io
6
- license: Apache-2.0
7
- summary: Demonstrates the use of InSpec Compliance Profile
8
- version: 1.0.0
9
- supports:
10
- - os-family: unix
1
+ name: profile
2
+ title: InSpec Example Profile
3
+ maintainer: Chef Software, Inc.
4
+ copyright: Chef Software, Inc.
5
+ copyright_email: support@chef.io
6
+ license: Apache-2.0
7
+ summary: Demonstrates the use of InSpec Compliance Profile
8
+ version: 1.0.0
9
+ supports:
10
+ - os-family: unix
@@ -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
data/inspec.gemspec CHANGED
@@ -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', '~> 1.2'
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', '~> 1.2'
30
+ spec.add_dependency 'thor', '~> 0.20'
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