inspec-core 2.3.5 → 2.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -8
  3. data/lib/bundles/inspec-compliance/api.rb +3 -353
  4. data/lib/bundles/inspec-compliance/configuration.rb +3 -102
  5. data/lib/bundles/inspec-compliance/http.rb +3 -115
  6. data/lib/bundles/inspec-compliance/support.rb +3 -35
  7. data/lib/bundles/inspec-compliance/target.rb +3 -142
  8. data/lib/inspec/base_cli.rb +4 -1
  9. data/lib/inspec/cli.rb +1 -1
  10. data/lib/inspec/control_eval_context.rb +2 -2
  11. data/lib/inspec/version.rb +1 -1
  12. data/lib/matchers/matchers.rb +3 -3
  13. data/lib/{bundles → plugins}/inspec-compliance/README.md +0 -0
  14. data/lib/plugins/inspec-compliance/lib/inspec-compliance.rb +12 -0
  15. data/lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb +358 -0
  16. data/lib/plugins/inspec-compliance/lib/inspec-compliance/api/login.rb +192 -0
  17. data/lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb +266 -0
  18. data/lib/plugins/inspec-compliance/lib/inspec-compliance/configuration.rb +103 -0
  19. data/lib/plugins/inspec-compliance/lib/inspec-compliance/http.rb +116 -0
  20. data/lib/{bundles → plugins/inspec-compliance/lib}/inspec-compliance/images/cc-token.png +0 -0
  21. data/lib/plugins/inspec-compliance/lib/inspec-compliance/support.rb +36 -0
  22. data/lib/plugins/inspec-compliance/lib/inspec-compliance/target.rb +143 -0
  23. data/lib/plugins/inspec-compliance/test/functional/inspec_compliance_test.rb +43 -0
  24. data/lib/{bundles → plugins}/inspec-compliance/test/integration/default/cli.rb +0 -0
  25. data/lib/plugins/inspec-compliance/test/unit/api/login_test.rb +190 -0
  26. data/lib/plugins/inspec-compliance/test/unit/api_test.rb +385 -0
  27. data/lib/plugins/inspec-compliance/test/unit/target_test.rb +155 -0
  28. data/lib/resources/processes.rb +19 -3
  29. metadata +17 -10
  30. data/lib/bundles/inspec-compliance.rb +0 -16
  31. data/lib/bundles/inspec-compliance/.kitchen.yml +0 -20
  32. data/lib/bundles/inspec-compliance/api/login.rb +0 -193
  33. data/lib/bundles/inspec-compliance/bootstrap.sh +0 -41
  34. data/lib/bundles/inspec-compliance/cli.rb +0 -276
@@ -0,0 +1,155 @@
1
+ require 'minitest/autorun'
2
+ require 'mocha/setup'
3
+ require_relative '../../lib/inspec-compliance/api.rb'
4
+
5
+ describe InspecPlugins::Compliance::Fetcher do
6
+ let(:config) { { 'server' => 'myserver' } }
7
+
8
+ describe 'the check_compliance_token method' do
9
+ let(:fetcher) { fetcher = InspecPlugins::Compliance::Fetcher.new('a/bad/url', config) }
10
+
11
+ it 'returns without error if token is set' do
12
+ config['token'] = 'my-token'
13
+ fetcher.class.check_compliance_token('http://test.com', config)
14
+ end
15
+
16
+ it 'returns an error when token is not set' do
17
+ ex = assert_raises(Inspec::FetcherFailure) { fetcher.class.check_compliance_token('http://test.com', config) }
18
+ ex.message.must_include "Cannot fetch http://test.com because your compliance token has not been\nconfigured."
19
+ end
20
+ end
21
+
22
+ describe 'when the server is an automate2 server' do
23
+ before { InspecPlugins::Compliance::API.expects(:is_automate2_server?).with(config).returns(true) }
24
+
25
+ it 'returns the correct owner and profile name' do
26
+ config['profile'] = ['admin', 'ssh-baseline', nil]
27
+ fetcher = InspecPlugins::Compliance::Fetcher.new('myserver/profile', config)
28
+ fetcher.send(:compliance_profile_name).must_equal 'admin/ssh-baseline'
29
+ end
30
+ end
31
+
32
+ describe 'when the server is an automate server pre-0.8.0' do
33
+ before { InspecPlugins::Compliance::API.expects(:is_automate_server_pre_080?).with(config).returns(true) }
34
+
35
+ it 'returns the correct profile name when the url is correct' do
36
+ fetcher = InspecPlugins::Compliance::Fetcher.new('myserver/myowner/myprofile/tar', config)
37
+ fetcher.send(:compliance_profile_name).must_equal 'myowner/myprofile'
38
+ end
39
+
40
+ it 'raises an exception if the url is malformed' do
41
+ fetcher = InspecPlugins::Compliance::Fetcher.new('a/bad/url', config)
42
+ proc { fetcher.send(:compliance_profile_name) }.must_raise RuntimeError
43
+ end
44
+ end
45
+
46
+ describe 'when the server is an automate server 0.8.0-or-later' do
47
+ before do
48
+ InspecPlugins::Compliance::API.expects(:is_automate_server_pre_080?).with(config).returns(false)
49
+ InspecPlugins::Compliance::API.expects(:is_automate_server_080_and_later?).with(config).returns(true)
50
+ end
51
+
52
+ it 'returns the correct profile name when the url is correct' do
53
+ fetcher = InspecPlugins::Compliance::Fetcher.new('myserver/profiles/myowner/myprofile/tar', config)
54
+ fetcher.send(:compliance_profile_name).must_equal 'myowner/myprofile'
55
+ end
56
+
57
+ it 'raises an exception if the url is malformed' do
58
+ fetcher = InspecPlugins::Compliance::Fetcher.new('a/bad/url', config)
59
+ proc { fetcher.send(:compliance_profile_name) }.must_raise RuntimeError
60
+ end
61
+ end
62
+
63
+ describe 'when the server is not an automate server (likely a compliance server)' do
64
+ before do
65
+ InspecPlugins::Compliance::API.expects(:is_automate_server_pre_080?).with(config).returns(false)
66
+ InspecPlugins::Compliance::API.expects(:is_automate_server_080_and_later?).with(config).returns(false)
67
+ end
68
+
69
+ it 'returns the correct profile name when the url is correct' do
70
+ fetcher = InspecPlugins::Compliance::Fetcher.new('myserver/owners/myowner/compliance/myprofile/tar', config)
71
+ fetcher.send(:compliance_profile_name).must_equal 'myowner/myprofile'
72
+ end
73
+
74
+ it 'raises an exception if the url is malformed' do
75
+ fetcher = InspecPlugins::Compliance::Fetcher.new('a/bad/url', config)
76
+ proc { fetcher.send(:compliance_profile_name) }.must_raise RuntimeError
77
+ end
78
+ end
79
+
80
+ describe 'when the server calls an automate profile' do
81
+ let(:profiles_result) do
82
+ [{ 'name'=>'ssh-baseline',
83
+ 'title'=>'InSpec Profile',
84
+ 'maintainer'=>'The Authors',
85
+ 'copyright'=>'The Authors',
86
+ 'copyright_email'=>'you@example.com',
87
+ 'license'=>'Apache-2.0',
88
+ 'summary'=>'An InSpec Compliance Profile',
89
+ 'version'=>'0.1.1',
90
+ 'owner'=>'admin',
91
+ 'supports'=>[],
92
+ 'depends'=>[],
93
+ 'sha256'=>'132j1kjdasfasdoaefaewo12312',
94
+ 'groups'=>[],
95
+ 'controls'=>[],
96
+ 'attributes'=>[],
97
+ 'latest_version'=>'' }]
98
+ end
99
+ before do
100
+ InspecPlugins::Compliance::Configuration.expects(:new).returns({ 'token' => '123abc', 'server' => 'https://a2.instance.com' })
101
+ end
102
+
103
+ it 'returns the correct profile name when parsing url' do
104
+ InspecPlugins::Compliance::API.stubs(:profiles).returns(['success', profiles_result])
105
+ fetcher = InspecPlugins::Compliance::Fetcher.resolve('compliance://admin/ssh-baseline')
106
+ assert = ['admin', 'ssh-baseline', nil]
107
+ fetcher.instance_variable_get(:"@config")['profile'].must_equal assert
108
+ end
109
+
110
+ it 'returns the correct profile name when parsing compliance hash' do
111
+ InspecPlugins::Compliance::API.stubs(:profiles).returns(['success', profiles_result])
112
+ hash = {
113
+ target: 'https://a2.instance.com/api/v0/compliance/tar',
114
+ compliance: 'admin/ssh-baseline',
115
+ sha256: '132j1kjdasfasdoaefaewo12312',
116
+ }
117
+ fetcher = InspecPlugins::Compliance::Fetcher.resolve(hash)
118
+ assert = ['admin', 'ssh-baseline', nil]
119
+ fetcher.instance_variable_get(:"@config")['profile'].must_equal assert
120
+ end
121
+ end
122
+
123
+ describe 'when the server provides a sha256 in the profiles_result' do
124
+ let(:profiles_result) do
125
+ [{ 'name'=>'ssh-baseline',
126
+ 'title'=>'InSpec Profile',
127
+ 'maintainer'=>'The Authors',
128
+ 'copyright'=>'The Authors',
129
+ 'copyright_email'=>'you@example.com',
130
+ 'license'=>'Apache-2.0',
131
+ 'summary'=>'An InSpec Compliance Profile',
132
+ 'version'=>'0.1.1',
133
+ 'owner'=>'admin',
134
+ 'supports'=>[],
135
+ 'depends'=>[],
136
+ 'sha256'=>'132j1kjdasfasdoaefaewo12312',
137
+ 'groups'=>[],
138
+ 'controls'=>[],
139
+ 'attributes'=>[],
140
+ 'latest_version'=>'' }]
141
+ end
142
+
143
+ before do
144
+ InspecPlugins::Compliance::Configuration.expects(:new).returns({ 'token' => '123abc', 'server' => 'https://a2.instance.com' })
145
+ end
146
+
147
+ it 'contains the upstream_sha256' do
148
+ InspecPlugins::Compliance::API.stubs(:profiles).returns(['success', profiles_result])
149
+ prof = profiles_result[0]
150
+ target = "compliance://#{prof['owner']}/#{prof['name']}"
151
+ fetcher = InspecPlugins::Compliance::Fetcher.resolve(target)
152
+ fetcher.upstream_sha256.must_equal prof['sha256']
153
+ end
154
+ end
155
+ end
@@ -126,7 +126,7 @@ module Inspec::Resources
126
126
  def ps_configuration_for_linux
127
127
  if busybox_ps?
128
128
  command = 'ps -o pid,vsz,rss,tty,stat,time,ruser,args'
129
- regex = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/
129
+ regex = /^\s*(\d+)\s+(\d+(?:\.\d+)?[gm]?)\s+(\d+(?:\.\d+)?[gm]?)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/
130
130
  field_map = {
131
131
  pid: 1,
132
132
  vsz: 2,
@@ -163,6 +163,18 @@ module Inspec::Resources
163
163
  @busybox_ps ||= inspec.command('ps --help').stderr.include?('BusyBox')
164
164
  end
165
165
 
166
+ def convert_to_kilobytes(param)
167
+ return param.to_i unless param.is_a?(String)
168
+
169
+ if param.end_with?('g')
170
+ (param[0..-2].to_f * 1024 * 1024).to_i
171
+ elsif param.end_with?('m')
172
+ (param[0..-2].to_f * 1024).to_i
173
+ else
174
+ param.to_i
175
+ end
176
+ end
177
+
166
178
  def build_process_list(command, regex, field_map)
167
179
  cmd = inspec.command(command)
168
180
  all = cmd.stdout.split("\n")[1..-1]
@@ -187,8 +199,12 @@ module Inspec::Resources
187
199
  end
188
200
 
189
201
  # ensure pid, vsz, and rss are integers for backward compatibility
190
- [:pid, :vsz, :rss].each do |int_param|
191
- process_data[int_param] = process_data[int_param].to_i if process_data.key?(int_param)
202
+ process_data[:pid] = process_data[:pid].to_i if process_data.key?(:pid)
203
+
204
+ # some ps variants (*cough* busybox) display vsz and rss as human readable MB or GB
205
+ [:vsz, :rss].each do |param|
206
+ next unless process_data.key?(param)
207
+ process_data[param] = convert_to_kilobytes(process_data[param])
192
208
  end
193
209
 
194
210
  # strip any newlines off the command
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.5
4
+ version: 2.3.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-28 00:00:00.000000000 Z
11
+ date: 2018-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train-core
@@ -494,19 +494,11 @@ files:
494
494
  - examples/profile/libraries/gordon_config.rb
495
495
  - inspec-core.gemspec
496
496
  - lib/bundles/README.md
497
- - lib/bundles/inspec-compliance.rb
498
- - lib/bundles/inspec-compliance/.kitchen.yml
499
- - lib/bundles/inspec-compliance/README.md
500
497
  - lib/bundles/inspec-compliance/api.rb
501
- - lib/bundles/inspec-compliance/api/login.rb
502
- - lib/bundles/inspec-compliance/bootstrap.sh
503
- - lib/bundles/inspec-compliance/cli.rb
504
498
  - lib/bundles/inspec-compliance/configuration.rb
505
499
  - lib/bundles/inspec-compliance/http.rb
506
- - lib/bundles/inspec-compliance/images/cc-token.png
507
500
  - lib/bundles/inspec-compliance/support.rb
508
501
  - lib/bundles/inspec-compliance/target.rb
509
- - lib/bundles/inspec-compliance/test/integration/default/cli.rb
510
502
  - lib/bundles/inspec-supermarket.rb
511
503
  - lib/bundles/inspec-supermarket/README.md
512
504
  - lib/bundles/inspec-supermarket/api.rb
@@ -614,6 +606,21 @@ files:
614
606
  - lib/plugins/inspec-artifact/lib/inspec-artifact/base.rb
615
607
  - lib/plugins/inspec-artifact/lib/inspec-artifact/cli.rb
616
608
  - lib/plugins/inspec-artifact/test/functional/inspec_artifact_test.rb
609
+ - lib/plugins/inspec-compliance/README.md
610
+ - lib/plugins/inspec-compliance/lib/inspec-compliance.rb
611
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/api.rb
612
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/api/login.rb
613
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/cli.rb
614
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/configuration.rb
615
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/http.rb
616
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/images/cc-token.png
617
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/support.rb
618
+ - lib/plugins/inspec-compliance/lib/inspec-compliance/target.rb
619
+ - lib/plugins/inspec-compliance/test/functional/inspec_compliance_test.rb
620
+ - lib/plugins/inspec-compliance/test/integration/default/cli.rb
621
+ - lib/plugins/inspec-compliance/test/unit/api/login_test.rb
622
+ - lib/plugins/inspec-compliance/test/unit/api_test.rb
623
+ - lib/plugins/inspec-compliance/test/unit/target_test.rb
617
624
  - lib/plugins/inspec-habitat/lib/inspec-habitat.rb
618
625
  - lib/plugins/inspec-habitat/lib/inspec-habitat/cli.rb
619
626
  - lib/plugins/inspec-habitat/lib/inspec-habitat/profile.rb
@@ -1,16 +0,0 @@
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 Compliance
9
- autoload :Configuration, 'inspec-compliance/configuration'
10
- autoload :HTTP, 'inspec-compliance/http'
11
- autoload :Support, 'inspec-compliance/support'
12
- autoload :API, 'inspec-compliance/api'
13
- end
14
-
15
- require 'inspec-compliance/cli'
16
- require 'inspec-compliance/target'
@@ -1,20 +0,0 @@
1
- ---
2
- driver:
3
- name: vagrant
4
- synced_folders:
5
- - ['../../../', '/inspec']
6
- network:
7
- - ['private_network', {ip: '192.168.251.2'}]
8
-
9
- provisioner:
10
- name: shell
11
-
12
- verifier:
13
- name: inspec
14
-
15
- platforms:
16
- - name: ubuntu-14.04
17
- suites:
18
- - name: default
19
- run_list:
20
- attributes:
@@ -1,193 +0,0 @@
1
- # encoding: utf-8
2
- # author: Christoph Hartmann
3
- # author: Dominik Ricter
4
- # author: Jerry Aldrich
5
-
6
- module Compliance
7
- class API
8
- module Login
9
- class CannotDetermineServerType < StandardError; end
10
-
11
- def login(options)
12
- raise ArgumentError, 'Please specify a server using `inspec compliance login https://SERVER`' unless options['server']
13
-
14
- options['server'] = URI("https://#{options['server']}").to_s if URI(options['server']).scheme.nil?
15
-
16
- options['server_type'] = Compliance::API.determine_server_type(options['server'], options['insecure'])
17
-
18
- case options['server_type']
19
- when :automate2
20
- Login::Automate2Server.login(options)
21
- when :automate
22
- Login::AutomateServer.login(options)
23
- when :compliance
24
- Login::ComplianceServer.login(options)
25
- else
26
- raise CannotDetermineServerType, "Unable to determine if #{options['server']} is a Chef Automate or Chef Compliance server"
27
- end
28
- end
29
-
30
- module Automate2Server
31
- def self.login(options)
32
- verify_thor_options(options)
33
-
34
- options['url'] = options['server'] + '/api/v0'
35
- token = options['dctoken'] || options['token']
36
- store_access_token(options, token)
37
- end
38
-
39
- def self.store_access_token(options, token)
40
- config = Compliance::Configuration.new
41
- config.clean
42
-
43
- config['automate'] = {}
44
- config['automate']['ent'] = 'automate'
45
- config['automate']['token_type'] = 'dctoken'
46
- config['server'] = options['url']
47
- config['user'] = options['user']
48
- config['owner'] = options['user']
49
- config['insecure'] = options['insecure'] || false
50
- config['server_type'] = options['server_type'].to_s
51
- config['token'] = token
52
- config['version'] = '0'
53
-
54
- config.store
55
- config
56
- end
57
-
58
- def self.verify_thor_options(o)
59
- error_msg = []
60
-
61
- error_msg.push('Please specify a user using `--user=\'USER\'`') if o['user'].nil?
62
-
63
- if o['token'].nil? && o['dctoken'].nil?
64
- error_msg.push('Please specify a token using `--token=\'APITOKEN\'`')
65
- end
66
-
67
- raise ArgumentError, error_msg.join("\n") unless error_msg.empty?
68
- end
69
- end
70
-
71
- module AutomateServer
72
- def self.login(options)
73
- verify_thor_options(options)
74
-
75
- options['url'] = options['server'] + '/compliance'
76
- token = options['dctoken'] || options['token']
77
- store_access_token(options, token)
78
- end
79
-
80
- def self.store_access_token(options, token)
81
- token_type = if options['token']
82
- 'usertoken'
83
- else
84
- 'dctoken'
85
- end
86
-
87
- config = Compliance::Configuration.new
88
-
89
- config.clean
90
-
91
- config['automate'] = {}
92
- config['automate']['ent'] = options['ent']
93
- config['automate']['token_type'] = token_type
94
- config['server'] = options['url']
95
- config['user'] = options['user']
96
- config['insecure'] = options['insecure'] || false
97
- config['server_type'] = options['server_type'].to_s
98
- config['token'] = token
99
- config['version'] = Compliance::API.version(config)
100
-
101
- config.store
102
- config
103
- end
104
-
105
- # Automate login requires `--ent`, `--user`, and either `--token` or `--dctoken`
106
- def self.verify_thor_options(o)
107
- error_msg = []
108
-
109
- error_msg.push('Please specify a user using `--user=\'USER\'`') if o['user'].nil?
110
- error_msg.push('Please specify an enterprise using `--ent=\'automate\'`') if o['ent'].nil?
111
-
112
- if o['token'].nil? && o['dctoken'].nil?
113
- error_msg.push('Please specify a token using `--token=\'AUTOMATE_TOKEN\'` or `--dctoken=\'DATA_COLLECTOR_TOKEN\'`')
114
- end
115
-
116
- raise ArgumentError, error_msg.join("\n") unless error_msg.empty?
117
- end
118
- end
119
-
120
- module ComplianceServer
121
- def self.login(options)
122
- compliance_verify_thor_options(options)
123
-
124
- options['url'] = options['server'] + '/api'
125
-
126
- if options['user'] && options['token']
127
- compliance_store_access_token(options, options['token'])
128
- elsif options['user'] && options['password']
129
- compliance_login_user_pass(options)
130
- elsif options['refresh_token']
131
- compliance_login_refresh_token(options)
132
- end
133
- end
134
-
135
- def self.compliance_login_user_pass(options)
136
- success, msg, token = Compliance::API.get_token_via_password(
137
- options['url'],
138
- options['user'],
139
- options['password'],
140
- options['insecure'],
141
- )
142
-
143
- raise msg unless success
144
- compliance_store_access_token(options, token)
145
- end
146
-
147
- def self.compliance_login_refresh_token(options)
148
- success, msg, token = Compliance::API.get_token_via_refresh_token(
149
- options['url'],
150
- options['refresh_token'],
151
- options['insecure'],
152
- )
153
-
154
- raise msg unless success
155
- compliance_store_access_token(options, token)
156
- end
157
-
158
- def self.compliance_store_access_token(options, token)
159
- config = Compliance::Configuration.new
160
- config.clean
161
-
162
- config['user'] = options['user'] if options['user']
163
- config['server'] = options['url']
164
- config['insecure'] = options['insecure'] || false
165
- config['server_type'] = options['server_type'].to_s
166
- config['token'] = token
167
- config['version'] = Compliance::API.version(config)
168
-
169
- config.store
170
- config
171
- end
172
-
173
- # Compliance login requires `--user` or `--refresh_token`
174
- # If `--user` then either `--password`, `--token`, or `--refresh-token`, is required
175
- def self.compliance_verify_thor_options(o)
176
- error_msg = []
177
-
178
- error_msg.push('Please specify a server using `inspec compliance login https://SERVER`') if o['server'].nil?
179
-
180
- if o['user'].nil? && o['refresh_token'].nil?
181
- error_msg.push('Please specify a `--user=\'USER\'` or a `--refresh-token=\'TOKEN\'`')
182
- end
183
-
184
- if o['user'] && o['password'].nil? && o['token'].nil? && o['refresh_token'].nil?
185
- error_msg.push('Please specify either a `--password`, `--token`, or `--refresh-token`')
186
- end
187
-
188
- raise ArgumentError, error_msg.join("\n") unless error_msg.empty?
189
- end
190
- end
191
- end
192
- end
193
- end