inspec-core 2.2.78 → 2.2.101

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd2c06a328a1d1852683797eaafa3b7391e39b82a22b8bb830bb965fabb6b1ab
4
- data.tar.gz: bc65f001fafc0b7b7fefe90309388cea38ad6968e081dc4a136f4cc1bb6ee531
3
+ metadata.gz: bad3e7476f7a3931284706247846b67ecabfb59be55430187e86dc6635436a4f
4
+ data.tar.gz: ec9f1586d0bde6037aa60a25ee9d758feb21e9715a45019baaa7189b9de599df
5
5
  SHA512:
6
- metadata.gz: '0822f141bda2c4640c154f61f3b819f05c154a213aaef9fca6e24b011d10c8344f85637bb356c4ec1ae6772db1fb27c88637beb0051607a0b71d1afb07977e00'
7
- data.tar.gz: aa6727726d7418819f3c905c058a49911fbb272bc0a7627307112015eb0fa455a5fbdd6592ebf6cbfe6a7d7416bd091b9a51139a8f5d8eb80ec72cedd307f3a6
6
+ metadata.gz: ca03041c8f5168ac760996394b57649208debb42e761dcca2fda628adc9850d72c4c962ceb34df836313169d1137a9217dc69b6f3fa3fa64c64f70298b514a18
7
+ data.tar.gz: 6a6aeb327d3664bb505b35d80a68d157eef7427f2bfe43062c2559ca6dc320bc4350be61fe85b26768a9d8348923099b726880609628162ee3478b6956146485
@@ -1,31 +1,62 @@
1
1
  # Change Log
2
2
  <!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
3
- <!-- latest_release 2.2.78 -->
4
- ## [v2.2.78](https://github.com/inspec/inspec/tree/v2.2.78) (2018-08-30)
3
+ <!-- latest_release 2.2.101 -->
4
+ ## [v2.2.101](https://github.com/inspec/inspec/tree/v2.2.101) (2018-09-14)
5
5
 
6
6
  #### Merged Pull Requests
7
- - Update demo site nom packages [#3343](https://github.com/inspec/inspec/pull/3343) ([miah](https://github.com/miah))
7
+ - Fix profile vendoring on Windows [#3378](https://github.com/inspec/inspec/pull/3378) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
8
8
  <!-- latest_release -->
9
9
 
10
- <!-- release_rollup since=2.2.70 -->
11
- ### Changes since 2.2.70 release
10
+ <!-- release_rollup since=2.2.78 -->
11
+ ### Changes since 2.2.78 release
12
12
 
13
13
  #### New Features
14
- - Add HTTP basic auth for URL based inspec deps [#3341](https://github.com/inspec/inspec/pull/3341) ([frezbo](https://github.com/frezbo)) <!-- 2.2.77 -->
15
- - Support erb rendering [#3338](https://github.com/inspec/inspec/pull/3338) ([frezbo](https://github.com/frezbo)) <!-- 2.2.76 -->
14
+ - Add string impact options for controls [#3359](https://github.com/inspec/inspec/pull/3359) ([jquick](https://github.com/jquick)) <!-- 2.2.96 -->
16
15
 
17
16
  #### Bug Fixes
18
- - fix skip message not being passed for merge [#3329](https://github.com/inspec/inspec/pull/3329) ([frezbo](https://github.com/frezbo)) <!-- 2.2.73 -->
17
+ - Fix the compliance target error checks [#3392](https://github.com/inspec/inspec/pull/3392) ([jquick](https://github.com/jquick)) <!-- 2.2.94 -->
18
+ - Prevent logs from showing up when running inspec json [#3391](https://github.com/inspec/inspec/pull/3391) ([jquick](https://github.com/jquick)) <!-- 2.2.93 -->
19
+ - Fixing AWS integration tests. [#3374](https://github.com/inspec/inspec/pull/3374) ([MartinLogan](https://github.com/MartinLogan)) <!-- 2.2.87 -->
20
+ - enforce utf encoding for cli output [#3376](https://github.com/inspec/inspec/pull/3376) ([chris-rock](https://github.com/chris-rock)) <!-- 2.2.86 -->
21
+ - Fix vendoring functional test cleanup [#3377](https://github.com/inspec/inspec/pull/3377) ([jquick](https://github.com/jquick)) <!-- 2.2.85 -->
22
+ - use multipart gem for upload to support upload on windows [#3369](https://github.com/inspec/inspec/pull/3369) ([chris-rock](https://github.com/chris-rock)) <!-- 2.2.84 -->
23
+ - ensure we use the mock backend when we upload profiles [#3370](https://github.com/inspec/inspec/pull/3370) ([chris-rock](https://github.com/chris-rock)) <!-- 2.2.83 -->
24
+
25
+ #### Enhancements
26
+ - do not show success message since its confusing [#3366](https://github.com/inspec/inspec/pull/3366) ([chris-rock](https://github.com/chris-rock)) <!-- 2.2.82 -->
27
+ - Harmonize vendoring (ensure archives are extracted and local paths do not vendor on exec) [#3286](https://github.com/inspec/inspec/pull/3286) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 2.2.81 -->
28
+ - handle errors from automate report and display them to the user [#3360](https://github.com/inspec/inspec/pull/3360) ([chris-rock](https://github.com/chris-rock)) <!-- 2.2.80 -->
19
29
 
20
30
  #### Merged Pull Requests
21
- - Update demo site nom packages [#3343](https://github.com/inspec/inspec/pull/3343) ([miah](https://github.com/miah)) <!-- 2.2.78 -->
22
- - Fix the brew command to install inspec [#3335](https://github.com/inspec/inspec/pull/3335) ([tas50](https://github.com/tas50)) <!-- 2.2.75 -->
23
- - Convert legacy supports to their platform counterparts [#3333](https://github.com/inspec/inspec/pull/3333) ([jquick](https://github.com/jquick)) <!-- 2.2.74 -->
24
- - bump inspec/train version [#3331](https://github.com/inspec/inspec/pull/3331) ([tomqwu](https://github.com/tomqwu)) <!-- 2.2.72 -->
25
- - Cached profiles with Compliance Fetcher [#3221](https://github.com/inspec/inspec/pull/3221) ([itmustbejj](https://github.com/itmustbejj)) <!-- 2.2.71 -->
31
+ - Fix profile vendoring on Windows [#3378](https://github.com/inspec/inspec/pull/3378) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 2.2.101 -->
32
+ - Add platforms schema command [#3346](https://github.com/inspec/inspec/pull/3346) ([jquick](https://github.com/jquick)) <!-- 2.2.97 -->
33
+ - Bump omnibus ruby to 2.5.1 [#3390](https://github.com/inspec/inspec/pull/3390) ([jquick](https://github.com/jquick)) <!-- 2.2.95 -->
34
+ - Add windows functional tests [#3385](https://github.com/inspec/inspec/pull/3385) ([jquick](https://github.com/jquick)) <!-- 2.2.92 -->
35
+ - Populate code for inspec json inheritance [#3386](https://github.com/inspec/inspec/pull/3386) ([jquick](https://github.com/jquick)) <!-- 2.2.91 -->
36
+ - Revert uuid change from A2 report [#3387](https://github.com/inspec/inspec/pull/3387) ([jquick](https://github.com/jquick)) <!-- 2.2.90 -->
37
+ - Implement InSpec global attributes [#3318](https://github.com/inspec/inspec/pull/3318) ([jquick](https://github.com/jquick)) <!-- 2.2.89 -->
38
+ - Update rubyzip to resolve a directory traversal security vulnerability. [#3388](https://github.com/inspec/inspec/pull/3388) ([miah](https://github.com/miah)) <!-- 2.2.88 -->
39
+ - Allow target-id passthrough [#3320](https://github.com/inspec/inspec/pull/3320) ([jquick](https://github.com/jquick)) <!-- 2.2.79 -->
26
40
  <!-- release_rollup -->
27
41
 
28
42
  <!-- latest_stable_release -->
43
+ ## [v2.2.78](https://github.com/inspec/inspec/tree/v2.2.78) (2018-08-30)
44
+
45
+ #### New Features
46
+ - Support erb rendering [#3338](https://github.com/inspec/inspec/pull/3338) ([frezbo](https://github.com/frezbo))
47
+ - Add HTTP basic auth for URL based inspec deps [#3341](https://github.com/inspec/inspec/pull/3341) ([frezbo](https://github.com/frezbo))
48
+
49
+ #### Bug Fixes
50
+ - fix skip message not being passed for merge [#3329](https://github.com/inspec/inspec/pull/3329) ([frezbo](https://github.com/frezbo))
51
+
52
+ #### Merged Pull Requests
53
+ - Cached profiles with Compliance Fetcher [#3221](https://github.com/inspec/inspec/pull/3221) ([itmustbejj](https://github.com/itmustbejj))
54
+ - bump inspec/train version [#3331](https://github.com/inspec/inspec/pull/3331) ([tomqwu](https://github.com/tomqwu))
55
+ - Convert legacy supports to their platform counterparts [#3333](https://github.com/inspec/inspec/pull/3333) ([jquick](https://github.com/jquick))
56
+ - Fix the brew command to install inspec [#3335](https://github.com/inspec/inspec/pull/3335) ([tas50](https://github.com/tas50))
57
+ - Update demo site nom packages [#3343](https://github.com/inspec/inspec/pull/3343) ([miah](https://github.com/miah))
58
+ <!-- latest_stable_release -->
59
+
29
60
  ## [v2.2.70](https://github.com/inspec/inspec/tree/v2.2.70) (2018-08-24)
30
61
 
31
62
  #### Enhancements
@@ -38,7 +69,6 @@
38
69
  - Add cloudlinux under redhat family [#2935](https://github.com/inspec/inspec/pull/2935) ([tarcinil](https://github.com/tarcinil))
39
70
  - Suppress logs for json-automate reporter [#3324](https://github.com/inspec/inspec/pull/3324) ([jquick](https://github.com/jquick))
40
71
  - Rebuild InSpec omni bundles [#3327](https://github.com/inspec/inspec/pull/3327) ([jquick](https://github.com/jquick))
41
- <!-- latest_stable_release -->
42
72
 
43
73
  ## [v2.2.64](https://github.com/inspec/inspec/tree/v2.2.64) (2018-08-17)
44
74
 
@@ -51,6 +51,7 @@ Each profile must have an `inspec.yml` file that defines the following informati
51
51
  * Use `inspec_version` to place SemVer constraints on the version of InSpec that the profile can run under.
52
52
  * Use `supports` to specify a list of supported platform targets.
53
53
  * Use `depends` to define a list of profiles on which this profile depends.
54
+ * Use `attributes` to define a list of attributes you can use in your controls.
54
55
 
55
56
  `name` is required; all other profile settings are optional. For example:
56
57
 
@@ -336,15 +337,68 @@ profile `my_dep` using the name `my_res2`.
336
337
 
337
338
  # Profile Attributes
338
339
 
339
- Attributes may be used in profiles to define secrets, such as user names and passwords, that should not otherwise be stored in plain-text in a cookbook. First specify a variable in the control for each secret, then add the secret to a YAML file located on the local machine, and then run `inspec exec` and specify the path to that Yaml file using the `--attrs` attribute.
340
+ Attributes are frequently used to parameterize a profile for use in different environments or targets. It can also be used define secrets, such as user names and passwords, that should not otherwise be stored in plain-text in a cookbook. Attributes may be set for the whole profile in the `inspec.yml`.
340
341
 
341
- For example, a control:
342
+ Attributes may contain the following options:
342
343
 
344
+ * Use `default` to set a default value for the attribute.
345
+ * Use `type` to restrict an attribute to a specific type (any, string, numeric, array, hash, boolean, regex).
346
+ * Use `required` to mandate the attribute has a default value or a value from a attribute YAML file.
347
+ * Use `description` to set a brief description for the attribute.
348
+
349
+
350
+ You can specify attributes in your `inspec.yml` using the `attributes` setting. For example, to add a `user` attribute for your profile:
351
+ ```YAML
352
+ attributes:
353
+ - name: user
354
+ type: string
355
+ default: bob
356
+ ```
357
+
358
+ Example of adding a array object of servers:
359
+ ```YAML
360
+ attributes:
361
+ - name: servers
362
+ type: array
363
+ default:
364
+ - server1
365
+ - server2
366
+ - server3
367
+ ```
368
+
369
+ To access an attribute you will use the `attribute` keyword. You can use this anywhere in your control code.
370
+
371
+ For example:
343
372
  ```Ruby
344
- # define these attributes on the top-level of your file and re-use them across all tests!
345
- val_user = attribute('user', default: 'alice', description: 'An identification for the user')
346
- val_password = attribute('password', description: 'A value for the password')
373
+ current_user = attribute('user')
374
+
375
+ control 'system-users' do
376
+ describe attribute('user') do
377
+ it { should eq 'bob' }
378
+ end
379
+
380
+ describe current_user do
381
+ it { should eq attribute('user') }
382
+ end
383
+ end
384
+ ```
385
+
386
+ For sensitive data it is recomended to use a secrets YAML file located on the local machine to populate the values of attributes. A secrets file will always overwrite a attributes default value. To use the secrets file run `inspec exec` and specify the path to that Yaml file using the `--attrs` attribute.
387
+
388
+ For example, a inspec.yml:
389
+ ```YAML
390
+ attributes:
391
+ - name: username
392
+ type: string
393
+ required: true
394
+ - name: password
395
+ type: string
396
+ required: true
397
+ ```
347
398
 
399
+ The control:
400
+
401
+ ```Ruby
348
402
  control 'system-users' do
349
403
  impact 0.8
350
404
  desc '
@@ -352,11 +406,11 @@ control 'system-users' do
352
406
  specified password.
353
407
  '
354
408
 
355
- val_user do
409
+ describe attribute('username') do
356
410
  it { should eq 'bob' }
357
411
  end
358
412
 
359
- describe val_password do
413
+ describe attribute('password') do
360
414
  it { should eq 'secret' }
361
415
  end
362
416
  end
@@ -365,7 +419,7 @@ end
365
419
  And a YAML file named `profile-attribute.yml`:
366
420
 
367
421
  ```YAML
368
- user: bob
422
+ username: bob
369
423
  password: secret
370
424
  ```
371
425
 
@@ -375,6 +429,50 @@ The following command runs the tests and applies the secrets specified in `profi
375
429
  $ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
376
430
  ```
377
431
 
432
+ To change your attributes for platform specific cases you can setup multiple `--attrs` files.
433
+
434
+ For example, a inspec.yml:
435
+ ```YAML
436
+ attributes:
437
+ - name: users
438
+ type: array
439
+ required: true
440
+ ```
441
+
442
+ A YAML file named `windows.yml`
443
+ ```YAML
444
+ users:
445
+ - Administrator
446
+ - Guest
447
+ - Randy
448
+ ```
449
+
450
+ A YAML file named `linux.yml`
451
+ ```YAML
452
+ users:
453
+ - root
454
+ - shadow
455
+ - rmadison
456
+ ```
457
+
458
+ The control file:
459
+ ```RUBY
460
+ control 'system-users' do
461
+ impact 0.8
462
+ desc 'Confirm the proper users are created on the system'
463
+
464
+ describe users do
465
+ its('usernames') { should eq attribute('users') }
466
+ end
467
+ end
468
+ ```
469
+
470
+ The following command runs the tests and applies the attributes specified:
471
+ ```bash
472
+ $ inspec exec examples/profile-attribute --attrs examples/windows.yml
473
+ $ inspec exec examples/profile-attribute --attrs examples/linux.yml
474
+ ```
475
+
378
476
  See the full example in the InSpec open source repository: [Example InSpec Profile with Attributes](https://github.com/chef/inspec/tree/master/examples/profile-attribute)
379
477
 
380
478
  # Profile files
@@ -7,7 +7,8 @@ license: Apache-2.0
7
7
  summary: Demonstrates the use of InSpec profile inheritance
8
8
  version: 1.0.0
9
9
  supports:
10
- - os-family: unix
10
+ - platform-family: unix
11
+ - platform-family: windows
11
12
  depends:
12
13
  - name: profile
13
14
  path: ../profile
@@ -11,7 +11,7 @@ title 'Gordon Config Checks'
11
11
  # EOF
12
12
  # ```
13
13
  control 'gordon-1.0' do
14
- impact 0.7
14
+ impact 'critical'
15
15
  title 'Verify the version number of Gordon'
16
16
  desc 'An optional description...'
17
17
  tag 'gordon'
@@ -28,6 +28,8 @@ control 'ssh-1' do
28
28
  ref 'DISA-RHEL6-SG - Section 9.2.1', url: 'http://iasecontent.disa.mil/stigs/zip/Jan2016/U_RedHat_6_V1R10_STIG.zip'
29
29
  ref 'http://people.redhat.com/swells/scap-security-guide/RHEL/6/output/ssg-centos6-guide-C2S.html'
30
30
 
31
+ only_if { platform.in_family?('unix') }
32
+
31
33
  describe file('/bin/sh') do
32
34
  it { should be_owned_by 'root' }
33
35
  end
@@ -7,4 +7,5 @@ license: Apache-2.0
7
7
  summary: Demonstrates the use of InSpec Compliance Profile
8
8
  version: 1.0.0
9
9
  supports:
10
- - os-family: unix
10
+ - platform-family: unix
11
+ - platform-family: windows
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.required_ruby_version = '>= 2.3'
24
24
 
25
- spec.add_dependency 'train-core', '~> 1.4', '>= 1.4.35'
25
+ spec.add_dependency 'train-core', '~> 1.4', '>= 1.4.37'
26
26
  spec.add_dependency 'thor', '~> 0.20'
27
27
  spec.add_dependency 'json', '>= 1.8', '< 3.0'
28
28
  spec.add_dependency 'method_source', '~> 0.8'
@@ -40,4 +40,5 @@ Gem::Specification.new do |spec|
40
40
  spec.add_dependency 'parslet', '~> 1.5'
41
41
  spec.add_dependency 'semverse'
42
42
  spec.add_dependency 'htmlentities'
43
+ spec.add_dependency 'multipart-post'
43
44
  end
@@ -69,7 +69,8 @@ module Compliance
69
69
  li("#{profile['title']} v#{profile['version']} (#{mark_text(owner + '/' + profile['name'])})")
70
70
  }
71
71
  else
72
- puts msg, 'Could not find any profiles'
72
+ puts msg if msg != 'success'
73
+ puts 'Could not find any profiles'
73
74
  exit 1
74
75
  end
75
76
  rescue Compliance::ServerConfigurationMissing
@@ -149,6 +150,12 @@ module Compliance
149
150
 
150
151
  o = options.dup
151
152
  configure_logger(o)
153
+
154
+ # only run against the mock backend, otherwise we run against the local system
155
+ o[:backend] = Inspec::Backend.create(target: 'mock://')
156
+ o[:check_mode] = true
157
+ o[:vendor_cache] = Inspec::Cache.new(o[:vendor_cache])
158
+
152
159
  # check the profile, we only allow to upload valid profiles
153
160
  profile = Inspec::Profile.for_target(path, o)
154
161
 
@@ -190,7 +197,9 @@ module Compliance
190
197
  end
191
198
 
192
199
  # if it is a directory, tar it to tmp directory
200
+ generated = false
193
201
  if File.directory?(path)
202
+ generated = true
194
203
  archive_path = Dir::Tmpname.create([profile_name, '.tar.gz']) {}
195
204
  puts "Generate temporary profile archive at #{archive_path}"
196
205
  profile.archive({ output: archive_path, ignore_errors: false, overwrite: true })
@@ -208,6 +217,9 @@ module Compliance
208
217
  end
209
218
  success, msg = Compliance::API.upload(config, config['owner'], pname, archive_path)
210
219
 
220
+ # delete temp file if it was temporary generated
221
+ File.delete(archive_path) if generated && File.exist?(archive_path)
222
+
211
223
  if success
212
224
  puts 'Successfully uploaded profile'
213
225
  else
@@ -3,6 +3,7 @@
3
3
  # author: Dominik Richter
4
4
 
5
5
  require 'net/http'
6
+ require 'net/http/post/multipart'
6
7
  require 'uri'
7
8
 
8
9
  module Compliance
@@ -60,7 +61,7 @@ module Compliance
60
61
 
61
62
  req.body_stream=File.open(file_path, 'rb')
62
63
  req.add_field('Content-Length', File.size(file_path))
63
- req.add_field('Content-Type', 'application/x-gtar')
64
+ req.add_field('Content-Type', 'application/x-gzip')
64
65
 
65
66
  boundary = 'INSPEC-PROFILE-UPLOAD'
66
67
  req.add_field('session', boundary)
@@ -77,24 +78,14 @@ module Compliance
77
78
  http.use_ssl = (uri.scheme == 'https')
78
79
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE if insecure
79
80
 
80
- req = Net::HTTP::Post.new(uri)
81
- headers.each do |key, value|
82
- req.add_field(key, value)
81
+ File.open(file_path) do |tar|
82
+ req = Net::HTTP::Post::Multipart.new(uri, 'file' => UploadIO.new(tar, 'application/x-gzip', File.basename(file_path)))
83
+ headers.each do |key, value|
84
+ req.add_field(key, value)
85
+ end
86
+ res = http.request(req)
87
+ return res
83
88
  end
84
-
85
- boundry = 'AaB03x'
86
- req.add_field('Content-Type', "multipart/form-data; boundary=#{boundry}")
87
-
88
- post_body = []
89
- post_body << "--#{boundry}\r\n"
90
- post_body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{File.basename(file_path)}\"\r\n"
91
- post_body << "Content-Type: application/x-gtar\r\n\r\n"
92
- post_body << File.read(file_path)
93
- post_body << "\r\n\r\n--#{boundry}--\r\n"
94
- req.body = post_body.join
95
-
96
- res=http.request(req)
97
- res
98
89
  end
99
90
 
100
91
  # sends a http requests
@@ -17,12 +17,12 @@ module Compliance
17
17
 
18
18
  def initialize(target, opts)
19
19
  super(target, opts)
20
+ @upstream_sha256 = ''
20
21
  if target.is_a?(Hash) && target.key?(:url)
21
22
  @target = target[:url]
22
23
  @upstream_sha256 = target[:sha256]
23
24
  elsif target.is_a?(String)
24
25
  @target = target
25
- @upstream_sha256 = ''
26
26
  end
27
27
  end
28
28
 
@@ -30,7 +30,7 @@ module Compliance
30
30
  upstream_sha256.empty? ? super : upstream_sha256
31
31
  end
32
32
 
33
- def self.check_compliance_token(config)
33
+ def self.check_compliance_token(uri, config)
34
34
  if config['token'].nil? && config['refresh_token'].nil?
35
35
  if config['server_type'] == 'automate'
36
36
  server = 'automate'
@@ -73,7 +73,7 @@ module Compliance
73
73
  if target.respond_to?(:key?) && target.key?(:sha256)
74
74
  profile_checksum = target[:sha256]
75
75
  else
76
- check_compliance_token(config)
76
+ check_compliance_token(uri, config)
77
77
  # verifies that the target e.g base/ssh exists
78
78
  # Call profiles directly instead of exist? to capture the results
79
79
  # so we can access the upstream sha256 from the results.
@@ -10,21 +10,23 @@ module Fetchers
10
10
  priority 0
11
11
 
12
12
  def self.resolve(target)
13
- local_path = if target.is_a?(String)
14
- resolve_from_string(target)
15
- elsif target.is_a?(Hash)
16
- resolve_from_hash(target)
17
- end
18
-
19
- new(local_path) if local_path
13
+ if target.is_a?(String)
14
+ local_path = resolve_from_string(target)
15
+ new(local_path) if local_path
16
+ elsif target.is_a?(Hash)
17
+ local_path = resolve_from_hash(target)
18
+ new(local_path, target) if local_path
19
+ end
20
20
  end
21
21
 
22
22
  def self.resolve_from_hash(target)
23
23
  return unless target.key?(:path)
24
24
 
25
- local_path = target[:path]
26
- local_path = File.expand_path(local_path, target[:cwd]) if target.key?(:cwd)
27
- local_path
25
+ if target.key?(:cwd)
26
+ File.expand_path(target[:path], target[:cwd])
27
+ else
28
+ target[:path]
29
+ end
28
30
  end
29
31
 
30
32
  def self.resolve_from_string(target)
@@ -36,15 +38,48 @@ module Fetchers
36
38
  target = target.tr('\\', '/')
37
39
  end
38
40
 
39
- target if File.exist?(target)
41
+ target if File.exist?(File.expand_path(target))
40
42
  end
41
43
 
42
- def initialize(target)
44
+ def initialize(target, opts = {})
43
45
  @target = target
46
+ @backend = opts[:backend]
47
+ @archive_shasum = nil
44
48
  end
45
49
 
46
- def fetch(_path)
47
- archive_path
50
+ def fetch(path)
51
+ # If `inspec exec` is used then we should not vendor/fetch. This makes
52
+ # local development easier and more predictable.
53
+ return @target if Inspec::BaseCLI.inspec_cli_command == :exec
54
+
55
+ # Skip vendoring if @backend is not set (example: ad hoc runners)
56
+ return @target unless @backend
57
+
58
+ if File.directory?(@target)
59
+ # Create an archive, checksum, and move to the vendor directory
60
+ Dir.mktmpdir do |tmpdir|
61
+ temp_archive = File.join(tmpdir, "#{File.basename(@target)}.tar.gz")
62
+ opts = {
63
+ backend: @backend,
64
+ output: temp_archive,
65
+ }
66
+
67
+ # Create a temporary archive at `opts[:output]`
68
+ Inspec::Profile.for_target(@target, opts).archive(opts)
69
+
70
+ checksum = perform_shasum(temp_archive)
71
+ final_path = File.join(path, checksum)
72
+ FileUtils.mkdir_p(final_path)
73
+ Inspec::FileProvider.for_path(temp_archive).extract(final_path)
74
+ end
75
+ else
76
+ # Verify profile (archive) is valid and extract to vendor directory
77
+ opts = { backend: @backend }
78
+ Inspec::Profile.for_target(@target, opts).check
79
+ Inspec::FileProvider.for_path(@target).extract(path)
80
+ end
81
+
82
+ @target
48
83
  end
49
84
 
50
85
  def archive_path
@@ -60,9 +95,17 @@ module Fetchers
60
95
  end
61
96
 
62
97
  def sha256
63
- return nil if File.directory?(@target)
64
- @archive_shasum ||=
65
- OpenSSL::Digest::SHA256.digest(File.read(@target)).unpack('H*')[0]
98
+ if !@archive_shasum.nil?
99
+ @archive_shasum
100
+ elsif File.directory?(@target)
101
+ nil
102
+ else
103
+ perform_shasum(@target)
104
+ end
105
+ end
106
+
107
+ def perform_shasum(target)
108
+ @archive_shasum ||= OpenSSL::Digest::SHA256.digest(File.read(target)).unpack('H*')[0]
66
109
  end
67
110
 
68
111
  def resolved_source