inspec 0.9.11 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/CHANGELOG.md +45 -2
  4. data/bin/inspec +53 -86
  5. data/examples/kitchen-ansible/.kitchen/default-ubuntu-1404.yml +2 -2
  6. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1404/.vagrant/machines/default/virtualbox/action_set_name +1 -1
  7. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1404/.vagrant/machines/default/virtualbox/id +1 -1
  8. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1404/.vagrant/machines/default/virtualbox/index_uuid +1 -1
  9. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1404/.vagrant/machines/default/virtualbox/private_key +25 -25
  10. data/examples/kitchen-ansible/.kitchen/logs/default-centos-71.log +0 -4
  11. data/examples/kitchen-ansible/.kitchen/logs/default-ubuntu-1204.log +0 -4
  12. data/examples/kitchen-ansible/.kitchen/logs/default-ubuntu-1404.log +395 -4
  13. data/examples/kitchen-ansible/.kitchen/logs/kitchen.log +3 -8
  14. data/examples/kitchen-ansible/Gemfile.lock +29 -25
  15. data/examples/kitchen-ansible/test/.DS_Store +0 -0
  16. data/examples/kitchen-ansible/test/integration/.DS_Store +0 -0
  17. data/examples/kitchen-azure/.kitchen.yml +30 -0
  18. data/examples/kitchen-azure/.kitchen/default-debian-80-20151022-x86-64.yml +1 -0
  19. data/examples/kitchen-azure/.kitchen/default-ubuntu-1204.yml +9 -0
  20. data/examples/kitchen-azure/.kitchen/logs/default-debian-80-20151022-x86-64.log +59 -0
  21. data/examples/kitchen-azure/.kitchen/logs/default-ubuntu-1204.log +27 -0
  22. data/{lib/resources/certificate.rb → examples/kitchen-azure/.kitchen/logs/default-windows2012-r2.log} +0 -0
  23. data/examples/kitchen-azure/.kitchen/logs/kitchen.log +29 -0
  24. data/examples/kitchen-azure/Berksfile +3 -0
  25. data/examples/kitchen-azure/Gemfile +20 -0
  26. data/examples/kitchen-azure/Gemfile.lock +273 -0
  27. data/examples/kitchen-azure/README.md +14 -0
  28. data/{lib/resources/private_key.rb → examples/kitchen-azure/credentials.sh} +0 -0
  29. data/examples/kitchen-azure/metadata.rb +7 -0
  30. data/examples/kitchen-azure/recipes/default.rb +6 -0
  31. data/examples/kitchen-azure/recipes/nginx.rb +30 -0
  32. data/examples/kitchen-azure/test/integration/default/web_spec.rb +28 -0
  33. data/examples/kitchen-chef/.kitchen/default-ubuntu-1404.yml +1 -1
  34. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1404/.vagrant/machines/default/virtualbox/action_set_name +1 -1
  35. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1404/.vagrant/machines/default/virtualbox/id +1 -1
  36. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1404/.vagrant/machines/default/virtualbox/index_uuid +1 -1
  37. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1404/.vagrant/machines/default/virtualbox/private_key +25 -25
  38. data/examples/kitchen-chef/.kitchen/logs/default-centos-71.log +0 -4
  39. data/examples/kitchen-chef/.kitchen/logs/default-ubuntu-1204.log +0 -4
  40. data/examples/kitchen-chef/.kitchen/logs/default-ubuntu-1404.log +3 -4
  41. data/examples/kitchen-chef/.kitchen/logs/kitchen.log +3 -8
  42. data/examples/kitchen-chef/Gemfile.lock +27 -24
  43. data/examples/kitchen-chef/test/integration/.DS_Store +0 -0
  44. data/examples/{kitchen-chef/.kitchen/default-ubuntu-1204.yml → kitchen-puppet/.kitchen/default-ubuntu-1404.yml} +1 -1
  45. data/examples/kitchen-puppet/.kitchen/kitchen-vagrant/kitchen-kitchen-puppet-default-ubuntu-1404/.vagrant/machines/default/virtualbox/action_set_name +1 -0
  46. data/examples/{kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-centos-71 → kitchen-puppet/.kitchen/kitchen-vagrant/kitchen-kitchen-puppet-default-ubuntu-1404}/.vagrant/machines/default/virtualbox/creator_uid +0 -0
  47. data/examples/kitchen-puppet/.kitchen/kitchen-vagrant/kitchen-kitchen-puppet-default-ubuntu-1404/.vagrant/machines/default/virtualbox/id +1 -0
  48. data/examples/kitchen-puppet/.kitchen/kitchen-vagrant/kitchen-kitchen-puppet-default-ubuntu-1404/.vagrant/machines/default/virtualbox/index_uuid +1 -0
  49. data/examples/kitchen-puppet/.kitchen/kitchen-vagrant/kitchen-kitchen-puppet-default-ubuntu-1404/.vagrant/machines/default/virtualbox/private_key +27 -0
  50. data/examples/{kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-centos-71 → kitchen-puppet/.kitchen/kitchen-vagrant/kitchen-kitchen-puppet-default-ubuntu-1404}/.vagrant/machines/default/virtualbox/synced_folders +0 -0
  51. data/examples/{kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-centos-71 → kitchen-puppet/.kitchen/kitchen-vagrant/kitchen-kitchen-puppet-default-ubuntu-1404}/Vagrantfile +3 -3
  52. data/examples/kitchen-puppet/.kitchen/logs/default-centos-71.log +0 -5
  53. data/examples/kitchen-puppet/.kitchen/logs/default-ubuntu-1204.log +0 -5
  54. data/examples/kitchen-puppet/.kitchen/logs/default-ubuntu-1404.log +305 -5
  55. data/examples/kitchen-puppet/.kitchen/logs/kitchen.log +6 -5
  56. data/examples/kitchen-puppet/.librarian/puppet/config +1 -1
  57. data/examples/kitchen-puppet/Gemfile.lock +22 -21
  58. data/examples/kitchen-puppet/test/integration/.DS_Store +0 -0
  59. data/examples/kitchen-puppet/test/integration/default/.DS_Store +0 -0
  60. data/examples/profile/controls/example.rb +7 -1
  61. data/lib/bundles/README.md +3 -0
  62. data/lib/bundles/inspec-compliance.rb +14 -0
  63. data/lib/bundles/inspec-compliance/README.md +20 -0
  64. data/lib/bundles/inspec-compliance/TODO.md +4 -0
  65. data/lib/bundles/inspec-compliance/api.rb +134 -0
  66. data/lib/bundles/inspec-compliance/cli.rb +146 -0
  67. data/lib/bundles/inspec-compliance/configuration.rb +52 -0
  68. data/lib/bundles/inspec-compliance/target.rb +61 -0
  69. data/lib/bundles/inspec-supermarket.rb +14 -0
  70. data/lib/bundles/inspec-supermarket/README.md +31 -0
  71. data/lib/bundles/inspec-supermarket/TODO.md +5 -0
  72. data/lib/bundles/inspec-supermarket/api.rb +58 -0
  73. data/lib/bundles/inspec-supermarket/cache.rb +30 -0
  74. data/lib/bundles/inspec-supermarket/cli.rb +54 -0
  75. data/lib/bundles/inspec-supermarket/target.rb +49 -0
  76. data/lib/inspec.rb +9 -2
  77. data/lib/inspec/metadata.rb +21 -7
  78. data/lib/inspec/plugins.rb +41 -0
  79. data/lib/inspec/plugins/cli.rb +24 -0
  80. data/lib/inspec/profile.rb +90 -61
  81. data/lib/inspec/rule.rb +9 -0
  82. data/lib/inspec/runner.rb +7 -3
  83. data/lib/inspec/runner_rspec.rb +19 -0
  84. data/lib/inspec/targets/archive.rb +14 -10
  85. data/lib/inspec/targets/tar.rb +3 -2
  86. data/lib/inspec/targets/url.rb +5 -4
  87. data/lib/inspec/targets/zip.rb +3 -2
  88. data/lib/inspec/version.rb +1 -1
  89. data/lib/resources/file.rb +7 -21
  90. data/lib/resources/os.rb +1 -1
  91. data/lib/resources/service.rb +15 -3
  92. data/lib/utils/base_cli.rb +131 -0
  93. data/lib/utils/find_files.rb +1 -1
  94. data/lib/utils/json_log.rb +17 -0
  95. data/test/helper.rb +39 -25
  96. data/test/integration/.kitchen.chef.yml +1 -1
  97. data/test/integration/.kitchen.ec2.yml +2 -0
  98. data/test/integration/.kitchen/default-aws-linux.yml +4 -0
  99. data/test/integration/.kitchen/default-centos-7.yml +4 -0
  100. data/test/integration/.kitchen/default-chef-solaris-113.yml +6 -0
  101. data/test/integration/.kitchen/default-chef-windows-server-2008r2-standard.yml +1 -1
  102. data/test/integration/.kitchen/default-debian-8.yml +4 -0
  103. data/test/integration/.kitchen/default-fedora-22.yml +4 -0
  104. data/test/integration/.kitchen/default-redhat-65.yml +4 -0
  105. data/test/integration/.kitchen/default-redhat-71.yml +4 -0
  106. data/test/integration/.kitchen/default-suse-11sp3.yml +4 -0
  107. data/test/integration/.kitchen/default-suse-12.yml +4 -0
  108. data/test/integration/.kitchen/default-suse-hi11sp3.yml +4 -0
  109. data/test/integration/.kitchen/default-ubuntu-1204.yml +4 -0
  110. data/test/integration/.kitchen/default-ubuntu-1404.yml +4 -0
  111. data/test/integration/.kitchen/default-ubuntu-1510.yml +4 -0
  112. data/test/integration/.kitchen/default-windows-2012r2.yml +6 -0
  113. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-solaris-113/.vagrant/machines/default/virtualbox/action_set_name +1 -0
  114. data/{examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1204 → test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-solaris-113}/.vagrant/machines/default/virtualbox/creator_uid +0 -0
  115. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-solaris-113/.vagrant/machines/default/virtualbox/id +1 -0
  116. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-solaris-113/.vagrant/machines/default/virtualbox/index_uuid +1 -0
  117. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-solaris-113/.vagrant/machines/default/virtualbox/private_key +27 -0
  118. data/{examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1204 → test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-solaris-113}/.vagrant/machines/default/virtualbox/synced_folders +0 -0
  119. data/test/integration/.kitchen/kitchen-vagrant/{kitchen-integration-default-chef-windows-server-2012r2-standard → kitchen-integration-default-chef-solaris-113}/Vagrantfile +2 -2
  120. data/test/integration/.kitchen/logs/default-aws-linux.log +0 -3
  121. data/test/integration/.kitchen/logs/default-centos-7.log +0 -3
  122. data/test/integration/.kitchen/logs/default-chef-solaris-113.log +0 -0
  123. data/test/integration/.kitchen/logs/default-chef-windows-server-2008r2-standard.log +43 -0
  124. data/test/integration/.kitchen/logs/default-chris-rock-omnios-r151014.log +41 -23
  125. data/test/integration/.kitchen/logs/default-debian-8.log +0 -3
  126. data/test/integration/.kitchen/logs/default-fedora-22.log +0 -3
  127. data/test/integration/.kitchen/logs/default-redhat-65.log +0 -3
  128. data/test/integration/.kitchen/logs/default-redhat-71.log +0 -3
  129. data/test/integration/.kitchen/logs/default-suse-11sp3.log +0 -3
  130. data/test/integration/.kitchen/logs/default-suse-12.log +0 -3
  131. data/test/integration/.kitchen/logs/default-suse-hi11sp3.log +37 -0
  132. data/test/integration/.kitchen/logs/default-ubuntu-1204.log +23 -3
  133. data/test/integration/.kitchen/logs/default-ubuntu-1404.log +0 -3
  134. data/test/integration/.kitchen/logs/default-ubuntu-1510.log +0 -3
  135. data/test/integration/.kitchen/logs/default-windows-2012r2.log +0 -2
  136. data/test/integration/.kitchen/logs/kitchen.log +3 -14
  137. data/test/integration/cookbooks/os_prepare/recipes/_upstart_service_centos.rb +21 -0
  138. data/test/integration/cookbooks/os_prepare/recipes/apache.rb +14 -0
  139. data/test/integration/cookbooks/os_prepare/recipes/service.rb +1 -0
  140. data/test/integration/test/integration/default/service_spec.rb +24 -0
  141. data/test/solaris_test.rb +70 -0
  142. data/test/unit/mock/cmd/initctl--version +5 -0
  143. data/test/unit/plugin_test.rb +46 -0
  144. data/test/unit/profile_test.rb +136 -21
  145. data/test/unit/resources/file_test.rb +13 -25
  146. metadata +105 -51
  147. data/examples/kitchen-ansible/.kitchen/default-centos-71.yml +0 -6
  148. data/examples/kitchen-ansible/.kitchen/default-ubuntu-1204.yml +0 -6
  149. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-centos-71/.vagrant/machines/default/virtualbox/action_set_name +0 -1
  150. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-centos-71/.vagrant/machines/default/virtualbox/id +0 -1
  151. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-centos-71/.vagrant/machines/default/virtualbox/index_uuid +0 -1
  152. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-centos-71/.vagrant/machines/default/virtualbox/private_key +0 -27
  153. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1204/.vagrant/machines/default/virtualbox/action_set_name +0 -1
  154. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1204/.vagrant/machines/default/virtualbox/id +0 -1
  155. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1204/.vagrant/machines/default/virtualbox/index_uuid +0 -1
  156. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1204/.vagrant/machines/default/virtualbox/private_key +0 -27
  157. data/examples/kitchen-ansible/.kitchen/kitchen-vagrant/kitchen-kitchen-ansible-default-ubuntu-1204/Vagrantfile +0 -9
  158. data/examples/kitchen-chef/.kitchen/default-centos-71.yml +0 -6
  159. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-centos-71/.vagrant/machines/default/virtualbox/action_set_name +0 -1
  160. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-centos-71/.vagrant/machines/default/virtualbox/creator_uid +0 -1
  161. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-centos-71/.vagrant/machines/default/virtualbox/id +0 -1
  162. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-centos-71/.vagrant/machines/default/virtualbox/index_uuid +0 -1
  163. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-centos-71/.vagrant/machines/default/virtualbox/private_key +0 -27
  164. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-centos-71/.vagrant/machines/default/virtualbox/synced_folders +0 -1
  165. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-centos-71/Vagrantfile +0 -9
  166. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1204/.vagrant/machines/default/virtualbox/action_set_name +0 -1
  167. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1204/.vagrant/machines/default/virtualbox/creator_uid +0 -1
  168. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1204/.vagrant/machines/default/virtualbox/id +0 -1
  169. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1204/.vagrant/machines/default/virtualbox/index_uuid +0 -1
  170. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1204/.vagrant/machines/default/virtualbox/private_key +0 -27
  171. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1204/.vagrant/machines/default/virtualbox/synced_folders +0 -1
  172. data/examples/kitchen-chef/.kitchen/kitchen-vagrant/kitchen-kitchen-chef-default-ubuntu-1204/Vagrantfile +0 -9
  173. data/test/integration/.kitchen/default-chef-windows-server-2012r2-standard.yml +0 -7
  174. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-windows-server-2012r2-standard/.vagrant/machines/default/virtualbox/action_set_name +0 -1
  175. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-windows-server-2012r2-standard/.vagrant/machines/default/virtualbox/creator_uid +0 -1
  176. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-windows-server-2012r2-standard/.vagrant/machines/default/virtualbox/id +0 -1
  177. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-windows-server-2012r2-standard/.vagrant/machines/default/virtualbox/index_uuid +0 -1
  178. data/test/integration/.kitchen/kitchen-vagrant/kitchen-integration-default-chef-windows-server-2012r2-standard/.vagrant/machines/default/virtualbox/synced_folders +0 -1
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ module Compliance
6
+ # stores configuration on local filesystem
7
+ class Configuration
8
+ def initialize
9
+ @config_path = File.join(Dir.home, '.inspec', 'compliance')
10
+ # ensure the directory is available
11
+ unless File.directory?(@config_path)
12
+ FileUtils.mkdir_p(@config_path)
13
+ end
14
+ # set config file path
15
+ @config_file = File.join(@config_path, '/config.json')
16
+ @config = {}
17
+
18
+ # load the data
19
+ get
20
+ end
21
+
22
+ # direct access to config
23
+ def [](key)
24
+ @config[key]
25
+ end
26
+
27
+ def []=(key, value)
28
+ @config[key] = value
29
+ end
30
+
31
+ # return the json data
32
+ def get
33
+ if File.exist?(@config_file)
34
+ file = File.read(@config_file)
35
+ @config = JSON.parse(file)
36
+ end
37
+ @config
38
+ end
39
+
40
+ # stores a hash to json
41
+ def store
42
+ File.open(@config_file, 'w') do |f|
43
+ f.write(@config.to_json)
44
+ end
45
+ end
46
+
47
+ # deletes data
48
+ def destroy
49
+ File.delete(@config_file)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ require 'uri'
6
+
7
+ # InSpec Target Helper for Chef Compliance
8
+ # reuses UrlHelper, but it knows the target server and the access token already
9
+ # similar to `inspec exec http://localhost:2134/owners/%base%/compliance/%ssh%/tar --user %token%`
10
+ module Compliance
11
+ class ChefComplianceHelper < Inspec::Targets::UrlHelper
12
+ def handles?(target)
13
+ # check for local scheme compliance://
14
+ uri = URI(target)
15
+ return unless URI(uri).scheme == 'compliance'
16
+
17
+ # check if we have a compliance token
18
+ config = Compliance::Configuration.new
19
+ return if config['token'].nil?
20
+
21
+ # get profile name
22
+ profile = get_profile_name(uri)
23
+
24
+ # verifies that the target e.g base/ssh exists
25
+ Compliance::API.exist?(profile)
26
+ rescue URI::Error => _e
27
+ false
28
+ end
29
+
30
+ # generates proper url
31
+ def resolve(target, opts = {})
32
+ profile = get_profile_name(URI(target))
33
+ # generates server url
34
+ target = build_target_url(profile)
35
+ config = Compliance::Configuration.new
36
+ opts['user'] = config['token']
37
+ puts target
38
+ super(target, opts)
39
+ end
40
+
41
+ # extracts profile name from url
42
+ def get_profile_name(uri)
43
+ uri.host + uri.path
44
+ end
45
+
46
+ def build_target_url(target)
47
+ owner, profile = target.split('/')
48
+ config = Compliance::Configuration.new
49
+ url = "#{config['server']}/owners/%owner_name%/compliance/%profile_name%/tar"
50
+ .gsub('%owner_name%', owner)
51
+ .gsub('%profile_name%', profile)
52
+ url
53
+ end
54
+
55
+ def to_s
56
+ 'Chef Compliance Profile Loader'
57
+ end
58
+ end
59
+
60
+ Inspec::Targets.add_module('chefcompliance', ChefComplianceHelper.new)
61
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ libdir = File.dirname(__FILE__)
6
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
7
+
8
+ module Supermarket
9
+ autoload :Configuration, 'inspec-supermarket/configuration'
10
+ autoload :API, 'inspec-supermarket/api'
11
+ end
12
+
13
+ require 'inspec-supermarket/cli'
14
+ require 'inspec-supermarket/target'
@@ -0,0 +1,31 @@
1
+ # InSpec Extension for Chef Supermarket
2
+
3
+ To use the CLI, this InSpec add-on adds the following commands:
4
+
5
+ * `$ inspec supermarket configure` - configures the supermarket server
6
+ * `$ inspec supermarket search` - searches for a compliance profile on supermarket
7
+ * `$ inspec supermarket exec nathenharvey/tmp-compliance-profile` - extends execute to load the profile
8
+
9
+ Compliance profiles from Supermarket can be executed in two mays:
10
+
11
+ - via supermarket exec: `inspec supermarket exec nathenharvey/tmp-compliance-profile`
12
+ - via supermarket scheme: `inspec exec supermarket://nathenharvey/tmp-compliance-profile`
13
+
14
+
15
+ # fetch all available profiles in local cache
16
+ # https://supermarket.chef.io/api/v1/tools-search\?q\=compliance_profile
17
+
18
+ # get the tool slug url
19
+ # https://supermarket.chef.io/api/v1/tools/tmp-compliance-profile
20
+ # https://supermarket.chef.io/api/v1/tools/tmp_compliance_profile
21
+ # response
22
+ # {
23
+ # "description": "An InSpec compliance profile for use with Chef Compliance Server.\r\n",
24
+ # "instructions": "## Installation\r\n\r\nDownload the [latest release](https://github.com/nathenharvey/tmp_compliance_profile/releases) from GitHub and upload the tar.gz to your Chef Compliance Server.\r\n\r\n## Controls Included\r\n\r\n* tmp-1.0 - A /tmp directory must exist\r\n* tmp-1.1 - The /tmp directory must be owned by the root user\r\n\r\n## License & Authors\r\n\r\n*Author:* Nathen Harvey\r\n\r\n*Copyright:* 2015-2016, Chef Software, Inc.\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n",
25
+ # "name": "/tmp Compliance Profile",
26
+ # "owner": "nathenharvey",
27
+ # "slug": "tmp-compliance-profile",
28
+ # "source_url": "https://github.com/nathenharvey/tmp_compliance_profile/",
29
+ # "type": "compliance_profile",
30
+ # "up_for_adoption": false
31
+ # }
@@ -0,0 +1,5 @@
1
+ # take source_url
2
+ # TODO:
3
+ # - cache supermarket values
4
+ # - configure supermarket url
5
+ # - read github url from tool url
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ module Supermarket
6
+ class API
7
+ def self.profiles
8
+ url = 'https://supermarket.chef.io/api/v1/tools-search'
9
+ data = get(url, { :q => 'compliance_profile' })
10
+ if !data.nil?
11
+ profiles = JSON.parse(data)
12
+ profiles['items']
13
+ # val = []
14
+ # # iterate over profiles
15
+ # profiles.each_key { |org|
16
+ # profiles[org].each_key { |name|
17
+ # val.push({ org: org, name: name})
18
+ # }
19
+ # }
20
+ # val
21
+ else
22
+ []
23
+ end
24
+ end
25
+
26
+ def self.info(slug)
27
+ url = "https://supermarket.chef.io/api/v1/tools/#{slug}"
28
+ data = get(url, {})
29
+ if !data.nil?
30
+ info = JSON.parse(data)
31
+ else
32
+ {}
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def self.get(url, params)
39
+ uri = URI.parse(url)
40
+ uri.query = URI.encode_www_form(params)
41
+ req = Net::HTTP::Get.new(uri)
42
+ send_request(uri, req)
43
+ end
44
+
45
+ def self.send_request(uri, req)
46
+ # send request
47
+ res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') {|http|
48
+ http.request(req)
49
+ }
50
+ if res.is_a?(Net::HTTPSuccess)
51
+ res.body
52
+ else
53
+ puts res.body
54
+ nil
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ module Supermarket
6
+ class Cache
7
+ def initialize
8
+ @config_path = File.join(ENV['HOME'], '/.inspec')
9
+ # ensure the directory is available
10
+ unless File.directory?(@config_path)
11
+ FileUtils.mkdir_p(@config_path)
12
+ end
13
+ # set cache file path
14
+ @cache_file = File.join(@config_path, '/supermarket-cache.json')
15
+ end
16
+
17
+ def update_cache(data)
18
+ File.open(@cache_file,"w") do |f|
19
+ f.write(data.to_json)
20
+ end
21
+ end
22
+
23
+ def retrieve_cache
24
+ if File.exists?(@cache_file)
25
+ file = File.read(@cache_file)
26
+ JSON.parse(file)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ module Supermarket
6
+ class SupermarketCLI < Inspec::BaseCLI
7
+ namespace 'supermarket'
8
+
9
+ desc 'configure SERVER', 'Changes the default supermarket https://supermarket.chef.io/api/v1/'
10
+ def configure(server)
11
+ end
12
+
13
+ desc 'profiles', 'list all available profiles in Chef Supermarket'
14
+ def profiles
15
+ # display profiles in format nathenharvey/tmp_compliance_profile
16
+ supermarket_profiles = Supermarket::API.profiles
17
+ supermarket_profiles.each { |p|
18
+ m = %r{^https://supermarket.chef.io/api/v1/tools/(?<slug>[\w-]+)(/)?$}.match(p['tool'])
19
+ puts "#{p['tool_owner']}/#{m[:slug]}"
20
+ }
21
+ end
22
+
23
+ desc 'exec PROFILE', 'executes a Supermarket profile'
24
+ option :id, type: :string,
25
+ desc: 'Attach a profile ID to all test results'
26
+ target_options
27
+ option :format, type: :string
28
+ def exec(*tests)
29
+ # iterate over tests and add compliance scheme
30
+ tests = tests.map { |t| 'supermarket://' + t }
31
+
32
+ # execute profile from inspec exec implementation
33
+ diagnose
34
+ run_tests(opts, tests)
35
+ end
36
+
37
+ desc 'info profile', 'display profile details'
38
+ def info(profile)
39
+ # display profiles in format nathenharvey/tmp-compliance-profile
40
+ # name: tmp_compliance_profile
41
+ # owner: nathenharvey
42
+ # description: ...
43
+ info = Supermarket::API.info('tmp-compliance-profile')
44
+ puts "name: #{info['slug']}"
45
+ puts "owner: #{info['owner']} "
46
+ puts "url: #{info['source_url']}"
47
+ puts "\n"
48
+ puts "description:\n#{info['description']}"
49
+ end
50
+ end
51
+
52
+ # register the subcommand to Inspec CLI registry
53
+ Inspec::Plugins::CLI.register(Supermarket::SupermarketCLI, "supermarket", "supermarket SUBCOMMAND ...", "Supermarket commands", {})
54
+ end
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+
5
+ require 'uri'
6
+
7
+ # InSpec Target Helper for Supermarket
8
+ module Supermarket
9
+ class SupermarketHelper < Inspec::Targets::UrlHelper
10
+ def handles?(profile)
11
+ # check for local scheme supermarket://
12
+ return unless URI(profile).scheme == 'supermarket'
13
+ # emulate supermarket namespace
14
+ profile == 'supermarket://nathenharvey/tmp-compliance-profile'
15
+ rescue URI::Error => e
16
+ false
17
+ end
18
+
19
+ # generates proper url
20
+ def resolve(profile, opts = {})
21
+ profile = get_profile_name(URI(target))
22
+ target = build_target_url(profile)
23
+ super(target, opts)
24
+ end
25
+
26
+ # extracts profile name from url
27
+ def get_profile_name(uri)
28
+ uri.host + uri.path
29
+ end
30
+
31
+ def build_target_url(target)
32
+
33
+ # read details from json
34
+ # extracts github url
35
+
36
+ supermarket, slug = target.split('/')
37
+ # search profile with slug
38
+ # get github url
39
+ # return github url
40
+ "https://github.com/nathenharvey/tmp_compliance_profile/"
41
+ end
42
+
43
+ def to_s
44
+ 'Chef Compliance Profile Loader'
45
+ end
46
+ end
47
+
48
+ Inspec::Targets.add_module('supermarket', Supermarket::SupermarketHelper.new)
49
+ end
@@ -12,9 +12,16 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
12
12
 
13
13
  require 'inspec/version'
14
14
  require 'inspec/profile'
15
- require 'inspec/resource'
16
15
  require 'inspec/rspec_json_formatter'
17
16
  require 'inspec/rule'
17
+ require 'matchers/matchers'
18
18
  require 'inspec/runner'
19
19
  require 'inspec/shell'
20
- require 'matchers/matchers'
20
+
21
+ # all utils that may be required by plugins
22
+ require 'utils/base_cli'
23
+
24
+ # ensure resource and plugins are loaded after runner, because the runner loads
25
+ # targets
26
+ require 'inspec/resource'
27
+ require 'inspec/plugins'
@@ -100,19 +100,27 @@ module Inspec
100
100
  !found.nil?
101
101
  end
102
102
 
103
- def valid?
104
- is_valid = true
103
+ # return all warn and errors
104
+ def valid
105
+ errors = []
106
+ warnings = []
107
+
105
108
  %w{ name version }.each do |field|
106
109
  next unless params[field.to_sym].nil?
107
- @logger.error("Missing profile #{field} in #{ref}")
108
- is_valid = false
110
+ errors.push("Missing profile #{field} in #{ref}")
109
111
  end
110
112
  %w{ title summary maintainer copyright }.each do |field|
111
113
  next unless params[field.to_sym].nil?
112
- @logger.warn("Missing profile #{field} in #{ref}")
113
- is_valid = false
114
+ warnings.push("Missing profile #{field} in #{ref}")
114
115
  end
115
- is_valid && @missing_methods.empty?
116
+
117
+ [errors, warnings]
118
+ end
119
+
120
+ # returns true or false
121
+ def valid?
122
+ errors, _warnings = valid
123
+ errors.empty? && unsupported.empty?
116
124
  end
117
125
 
118
126
  def method_missing(sth, *args)
@@ -120,6 +128,10 @@ module Inspec
120
128
  @missing_methods.push(sth)
121
129
  end
122
130
 
131
+ def unsupported
132
+ @missing_methods
133
+ end
134
+
123
135
  def self.symbolize_keys(hash)
124
136
  hash.each_with_object({}) {|(k, v), h|
125
137
  v = symbolize_keys(v) if v.is_a?(Hash)
@@ -146,6 +158,8 @@ module Inspec
146
158
  end
147
159
 
148
160
  def self.from_ref(ref, contents, profile_id, logger = nil)
161
+ # NOTE there doesn't have to exist an actual file, it may come from an
162
+ # archive (i.e., contents)
149
163
  case File.basename(ref)
150
164
  when 'inspec.yml'
151
165
  from_yaml(ref, contents, profile_id, logger)
@@ -2,8 +2,49 @@
2
2
  # author: Dominik Richter
3
3
  # author: Christoph Hartmann
4
4
 
5
+ require 'forwardable'
6
+
5
7
  module Inspec
8
+ # Resource Plugins
6
9
  module Plugins
7
10
  autoload :Resource, 'inspec/plugins/resource'
11
+ autoload :CLI, 'inspec/plugins/cli'
12
+ end
13
+
14
+ class PluginCtl
15
+ extend Forwardable
16
+
17
+ attr_reader :registry
18
+ def_delegator :registry, :keys, :list
19
+
20
+ def initialize(home = nil)
21
+ @home = home || File.join(Dir.home, '.inspec', 'plugins')
22
+ @paths = Dir[File.join(@home, '**{,/*/**}', '*.gemspec')]
23
+ .map { |x| File.dirname(x) }
24
+ .map { |x| Dir[File.join(x, 'lib', 'inspec-*.rb')] }
25
+ .flatten
26
+
27
+ # load bundled plugins
28
+ bundled_dir = File.expand_path(File.dirname(__FILE__))
29
+ @paths += Dir[File.join(bundled_dir, '..', 'bundles', 'inspec-*.rb')].flatten
30
+
31
+ # map paths to names
32
+ @registry = Hash[@paths.map { |x|
33
+ [File.basename(x, '.rb'), x]
34
+ }]
35
+ end
36
+
37
+ def load(name)
38
+ path = @registry[name]
39
+ if path.nil?
40
+ fail "Couldn't find plugin #{name}. Searching in #{@home}"
41
+ end
42
+ # puts "Loading plugin #{name} from #{path}"
43
+ require path
44
+ end
8
45
  end
9
46
  end
47
+
48
+ # Load all plugins on startup
49
+ ctl = Inspec::PluginCtl.new
50
+ ctl.list.each { |x| ctl.load(x) }