inspec 1.42.3 → 1.43.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,7 +32,7 @@ module Compliance
32
32
  if config['token'].nil? && config['refresh_token'].nil?
33
33
  if config['server_type'] == 'automate'
34
34
  server = 'automate'
35
- msg = 'inspec compliance login_automate https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --usertoken USERTOKEN'
35
+ msg = 'inspec compliance login https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --token USERTOKEN'
36
36
  else
37
37
  server = 'compliance'
38
38
  msg = "inspec compliance login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
@@ -90,8 +90,7 @@ EOF
90
90
 
91
91
  raise 'Unable to determine compliance profile name. This can be caused by ' \
92
92
  'an incorrect server in your configuration. Try to login to compliance ' \
93
- 'via the `inspec compliance login` or `inspec compliance login_automate` ' \
94
- 'commands.' if m.nil?
93
+ 'via the `inspec compliance login` command.' if m.nil?
95
94
 
96
95
  "#{m[:owner]}/#{m[:id]}"
97
96
  end
@@ -2,10 +2,11 @@
2
2
 
3
3
  module Inspec
4
4
  class Control
5
- attr_accessor :id, :title, :desc, :impact, :tests, :tags
5
+ attr_accessor :id, :title, :desc, :impact, :tests, :tags, :refs
6
6
  def initialize
7
7
  @tests = []
8
8
  @tags = []
9
+ @refs = []
9
10
  end
10
11
 
11
12
  def add_test(t)
@@ -20,12 +21,13 @@ module Inspec
20
21
  { id: id, title: title, desc: desc, impact: impact, tests: tests.map(&:to_hash), tags: tags.map(&:to_hash) }
21
22
  end
22
23
 
23
- def to_ruby
24
+ def to_ruby # rubocop:disable Metrics/AbcSize
24
25
  res = ["control #{id.inspect} do"]
25
26
  res.push " title #{title.inspect}" unless title.to_s.empty?
26
27
  res.push " desc #{prettyprint_text(desc, 2)}" unless desc.to_s.empty?
27
28
  res.push " impact #{impact}" unless impact.nil?
28
29
  tags.each { |t| res.push(indent(t.to_ruby, 2)) }
30
+ refs.each { |t| res.push(" ref #{print_ref(t)}") }
29
31
  tests.each { |t| res.push(indent(t.to_ruby, 2)) }
30
32
  res.push 'end'
31
33
  res.join("\n")
@@ -33,6 +35,12 @@ module Inspec
33
35
 
34
36
  private
35
37
 
38
+ def print_ref(x)
39
+ return x.inspect if x.is_a?(String)
40
+ raise "Cannot process the ref: #{x}" unless x.is_a?(Hash)
41
+ '('+x.inspect+')'
42
+ end
43
+
36
44
  # Pretty-print a text block of InSpec code
37
45
  #
38
46
  # @param s [String] should not be empty
@@ -106,7 +106,8 @@ module Inspec
106
106
  # we share the backend between profiles.
107
107
  #
108
108
  # This will cause issues if a profile attempts to load a file via `inspec.profile.file`
109
- @backend = options[:backend].nil? ? Inspec::Backend.create(options) : options[:backend].dup
109
+ train_options = options.select { |k, _| k != 'target' } # See https://github.com/chef/inspec/pull/1646
110
+ @backend = options[:backend].nil? ? Inspec::Backend.create(train_options) : options[:backend].dup
110
111
  @runtime_profile = RuntimeProfile.new(self)
111
112
  @backend.profile = @runtime_profile
112
113
 
@@ -84,12 +84,15 @@ require 'resources/bash'
84
84
  require 'resources/bond'
85
85
  require 'resources/bridge'
86
86
  require 'resources/command'
87
+ require 'resources/cran'
88
+ require 'resources/cpan'
87
89
  require 'resources/crontab'
88
90
  require 'resources/dh_params'
89
91
  require 'resources/directory'
90
92
  require 'resources/docker'
91
93
  require 'resources/docker_container'
92
94
  require 'resources/docker_image'
95
+ require 'resources/elasticsearch'
93
96
  require 'resources/etc_fstab'
94
97
  require 'resources/etc_group'
95
98
  require 'resources/etc_hosts_allow_deny'
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.42.3'.freeze
7
+ VERSION = '1.43.5'.freeze
8
8
  end
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+ # author: Markus Grobelin
5
+
6
+ # Usage:
7
+ # describe cpan('DBD::Pg') do
8
+ # it { should be_installed }
9
+ # end
10
+ #
11
+
12
+ module Inspec::Resources
13
+ class CpanPackage < Inspec.resource(1)
14
+ name 'cpan'
15
+ desc 'Use the `cpan` InSpec audit resource to test Perl modules that are installed by system packages or the CPAN installer.'
16
+ example "
17
+ describe cpan('DBD::Pg') do
18
+ it { should be_installed }
19
+ end
20
+ "
21
+
22
+ def initialize(package_name, perl_lib_path = nil)
23
+ @package_name = package_name
24
+ @perl_lib_path = perl_lib_path
25
+ @perl_cmd = 'perl'
26
+
27
+ # this resource is not supported on Windows
28
+ return skip_resource 'The `cpan` resource is not supported on your OS yet.' if inspec.os.windows?
29
+ return skip_resource 'perl not found' unless inspec.command(@perl_cmd).exist?
30
+ end
31
+
32
+ def info
33
+ return @info if defined?(@info)
34
+
35
+ @info = {}
36
+ @info[:type] = 'cpan'
37
+ @info[:name] = @package_name
38
+ # set PERL5LIB environment variable if a custom lib path is given
39
+ lib_path = @perl_lib_path.nil? ? '' : "PERL5LIB=#{@perl_lib_path} "
40
+ cmd = inspec.command("#{lib_path+@perl_cmd} -le 'eval \"require $ARGV[0]\" and print $ARGV[0]->VERSION or exit 1' #{@package_name}")
41
+ @info[:installed] = cmd.exit_status.zero?
42
+ return @info unless cmd.exit_status.zero?
43
+
44
+ @info[:version] = cmd.stdout.strip
45
+ @info
46
+ end
47
+
48
+ def installed?
49
+ info[:installed] == true
50
+ end
51
+
52
+ def version
53
+ info[:version]
54
+ end
55
+
56
+ def to_s
57
+ "Perl Module #{@package_name}"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+ # author: Christoph Hartmann
3
+ # author: Dominik Richter
4
+ # author: Markus Grobelin
5
+
6
+ # Usage:
7
+ # describe cran('DBI') do
8
+ # it { should be_installed }
9
+ # end
10
+ #
11
+
12
+ module Inspec::Resources
13
+ class CranPackage < Inspec.resource(1)
14
+ name 'cran'
15
+ desc 'Use the `cran` InSpec audit resource to test R modules that are installed from CRAN package repository.'
16
+ example "
17
+ describe cran('DBI') do
18
+ it { should be_installed }
19
+ end
20
+ "
21
+
22
+ def initialize(package_name)
23
+ @package_name = package_name
24
+ @r_cmd = 'Rscript'
25
+
26
+ # this resource is not supported on Windows
27
+ return skip_resource 'The `cran` resource is not supported on your OS yet.' if inspec.os.windows?
28
+ return skip_resource 'Rscript not found' unless inspec.command(@r_cmd).exist?
29
+ end
30
+
31
+ def info
32
+ return @info if defined?(@info)
33
+
34
+ @info = {}
35
+ @info[:type] = 'cran'
36
+ @info[:name] = @package_name
37
+ cmd = inspec.command("#{@r_cmd} -e 'packageVersion(\"#{@package_name}\")'")
38
+ return @info unless cmd.exit_status.zero?
39
+
40
+ # Extract package version from Rscript output
41
+ # Output includes unicode punctuation (backticks) characters like so:
42
+ # [1] '0.5.1'
43
+ #
44
+ # So make sure command output is converted to unicode, as it returns ASCII-8BIT by default
45
+ utf8_stdout = cmd.stdout.chomp.force_encoding(Encoding::UTF_8)
46
+ params = /^\[\d+\]\s+(?:\p{Initial_Punctuation})(.+)(?:\p{Final_Punctuation})$/.match(utf8_stdout)
47
+ @info[:installed] = !params.nil?
48
+ return @info unless @info[:installed]
49
+
50
+ @info[:version] = params[1]
51
+ @info
52
+ end
53
+
54
+ def installed?
55
+ info[:installed] == true
56
+ end
57
+
58
+ def version
59
+ info[:version]
60
+ end
61
+
62
+ def to_s
63
+ "R Module #{@package_name}"
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,172 @@
1
+ # encoding: utf-8
2
+
3
+ require 'utils/filter'
4
+ require 'hashie/mash'
5
+ require 'resources/package'
6
+
7
+ module Inspec::Resources
8
+ class Elasticsearch < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
9
+ name 'elasticsearch'
10
+ desc "Use the Elasticsearch InSpec audit resource to test the status of nodes in
11
+ an Elasticsearch cluster."
12
+
13
+ example "
14
+ describe elasticsearch('http://eshost.mycompany.biz:9200/', username: 'elastic', password: 'changeme', ssl_verify: false) do
15
+ its('node_count') { should >= 3 }
16
+ end
17
+
18
+ describe elasticsearch do
19
+ its('node_name') { should include 'node1' }
20
+ its('os') { should_not include 'MacOS' }
21
+ its('version') { should cmp > 1.2.0 }
22
+ end
23
+ "
24
+
25
+ filter = FilterTable.create
26
+ filter.add_accessor(:where)
27
+ .add_accessor(:entries)
28
+ .add(:cluster_name, field: 'cluster_name')
29
+ .add(:node_name, field: 'name')
30
+ .add(:transport_address, field: 'transport_address')
31
+ .add(:host, field: 'host')
32
+ .add(:ip, field: 'ip')
33
+ .add(:version, field: 'version')
34
+ .add(:build_hash, field: 'build_hash')
35
+ .add(:total_indexing_buffer, field: 'total_indexing_buffer')
36
+ .add(:roles, field: 'roles')
37
+ .add(:settings, field: 'settings')
38
+ .add(:os, field: 'os')
39
+ .add(:process, field: 'process')
40
+ .add(:jvm, field: 'jvm')
41
+ .add(:transport, field: 'transport')
42
+ .add(:http, field: 'http')
43
+ .add(:plugins, field: 'plugins')
44
+ .add(:plugin_list, field: 'plugin_list')
45
+ .add(:modules, field: 'modules')
46
+ .add(:module_list, field: 'module_list')
47
+ .add(:node_id, field: 'node_id')
48
+ .add(:ingest, field: 'ingest')
49
+ .add(:exists?) { |x| !x.entries.empty? }
50
+ .add(:node_count) { |t, _|
51
+ t.entries.length
52
+ }
53
+
54
+ filter.connect(self, :nodes)
55
+
56
+ attr_reader :nodes, :url
57
+
58
+ def initialize(opts = {})
59
+ return skip_resource 'Package `curl` not avaiable on the host' unless inspec.command('curl').exist?
60
+
61
+ @url = opts.fetch(:url, 'http://localhost:9200')
62
+
63
+ username = opts.fetch(:username, nil)
64
+ password = opts.fetch(:password, nil)
65
+ ssl_verify = opts.fetch(:ssl_verify, true)
66
+
67
+ cmd = inspec.command(curl_command_string(username, password, ssl_verify))
68
+
69
+ # after implementation of PR #2235, this begin..rescue won't be necessary.
70
+ # The checks in verify_curl_success! can raise their own skip message exception.
71
+ begin
72
+ verify_curl_success!(cmd)
73
+ rescue => e
74
+ return skip_resource e.message
75
+ end
76
+
77
+ begin
78
+ content = JSON.parse(cmd.stdout)
79
+ # after implementation of PR #2235, this can be broken out of the begin..rescue
80
+ # clause. The checks in verify_json_payload! can raise their own skip message exception.
81
+ verify_json_payload!(content)
82
+ rescue JSON::ParserError => e
83
+ return skip_resource "Couldn't parse the Elasticsearch response: #{e.message}"
84
+ rescue => e
85
+ return skip_resource e.message
86
+ end
87
+
88
+ @nodes = parse_cluster(content)
89
+ end
90
+
91
+ def to_s
92
+ "Elasticsearch Cluster #{url}"
93
+ end
94
+
95
+ private
96
+
97
+ def parse_cluster(content)
98
+ return [] unless content['nodes']
99
+
100
+ nodes = []
101
+
102
+ content['nodes'].each do |node_id, node_data|
103
+ node_data = fix_mash_key_collision(node_data)
104
+
105
+ node = Hashie::Mash.new(node_data)
106
+ node.node_id = node_id
107
+ node.plugin_list = node.plugins.map(&:name)
108
+ node.module_list = node.modules.map(&:name)
109
+ node.cluster_name = node.settings.cluster.name
110
+ nodes << node
111
+ end
112
+
113
+ nodes
114
+ end
115
+
116
+ #
117
+ # Hashie::Mash will throw warnings if the Mash contains a key that is the same as a built-in
118
+ # method on a Hashie::Mash instance. This is a crude way of avoiding those warnings without
119
+ # hard-coding a bunch of key renames.
120
+ #
121
+ # Any key that is in conflict will be renamed "es_ORIGINALKEY"
122
+ #
123
+ def fix_mash_key_collision(data)
124
+ test_mash = Hashie::Mash.new
125
+
126
+ new_data = {}
127
+ data.each do |key, value|
128
+ new_key = test_mash.respond_to?(key.to_sym) ? "es_#{key}" : key
129
+ new_value = value.is_a?(Hash) ? fix_mash_key_collision(value) : value
130
+
131
+ new_data[new_key] = new_value
132
+ end
133
+
134
+ new_data
135
+ end
136
+
137
+ def curl_command_string(username, password, ssl_verify)
138
+ cmd_string = ['curl']
139
+ cmd_string << '-k' unless ssl_verify
140
+ cmd_string << "-H 'Content-Type: application/json'"
141
+ cmd_string << " -u #{username}:#{password}" unless username.nil? || password.nil?
142
+ cmd_string << URI.join(url, '_nodes')
143
+
144
+ cmd_string.join(' ')
145
+ end
146
+
147
+ def verify_curl_success!(cmd)
148
+ # the following lines captures known possible curl command errors and provides compact skip resource messeges
149
+ if cmd.stderr =~ /Failed to connect/
150
+ raise "Connection refused - please check the URL #{url} for accuracy"
151
+ end
152
+
153
+ if cmd.stderr =~ /Peer's Certificate issuer is not recognized/
154
+ raise 'Connection refused - peer certificate issuer is not recognized'
155
+ end
156
+
157
+ if !cmd.exit_status.zero?
158
+ raise "Error fetching Elastcsearch data from curl #{url}: #{cmd.stderr}"
159
+ end
160
+ end
161
+
162
+ def verify_json_payload!(content)
163
+ unless content['error'].nil?
164
+ raise "#{content['error']['type']}: #{content['error']['reason']}"
165
+ end
166
+
167
+ if content['_nodes']['successful'].zero?
168
+ raise 'No successful nodes available in cluster'
169
+ end
170
+ end
171
+ end
172
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.42.3
4
+ version: 1.43.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-18 00:00:00.000000000 Z
11
+ date: 2017-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train
@@ -324,6 +324,8 @@ files:
324
324
  - docs/resources/bridge.md.erb
325
325
  - docs/resources/bsd_service.md.erb
326
326
  - docs/resources/command.md.erb
327
+ - docs/resources/cpan.md.erb
328
+ - docs/resources/cran.md.erb
327
329
  - docs/resources/crontab.md.erb
328
330
  - docs/resources/csv.md.erb
329
331
  - docs/resources/dh_params.md
@@ -331,6 +333,7 @@ files:
331
333
  - docs/resources/docker.md.erb
332
334
  - docs/resources/docker_container.md.erb
333
335
  - docs/resources/docker_image.md.erb
336
+ - docs/resources/elasticsearch.md.erb
334
337
  - docs/resources/etc_fstab.md.erb
335
338
  - docs/resources/etc_group.md.erb
336
339
  - docs/resources/etc_hosts.md.erb
@@ -467,6 +470,7 @@ files:
467
470
  - lib/bundles/inspec-compliance/.kitchen.yml
468
471
  - lib/bundles/inspec-compliance/README.md
469
472
  - lib/bundles/inspec-compliance/api.rb
473
+ - lib/bundles/inspec-compliance/api/login.rb
470
474
  - lib/bundles/inspec-compliance/bootstrap.sh
471
475
  - lib/bundles/inspec-compliance/cli.rb
472
476
  - lib/bundles/inspec-compliance/configuration.rb
@@ -572,6 +576,8 @@ files:
572
576
  - lib/resources/bond.rb
573
577
  - lib/resources/bridge.rb
574
578
  - lib/resources/command.rb
579
+ - lib/resources/cpan.rb
580
+ - lib/resources/cran.rb
575
581
  - lib/resources/crontab.rb
576
582
  - lib/resources/csv.rb
577
583
  - lib/resources/dh_params.rb
@@ -579,6 +585,7 @@ files:
579
585
  - lib/resources/docker.rb
580
586
  - lib/resources/docker_container.rb
581
587
  - lib/resources/docker_image.rb
588
+ - lib/resources/elasticsearch.rb
582
589
  - lib/resources/etc_fstab.rb
583
590
  - lib/resources/etc_group.rb
584
591
  - lib/resources/etc_hosts.rb