inspec 0.33.2 → 0.34.0

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
  SHA1:
3
- metadata.gz: 2f4f2b2442e3a19f101d6d04c0a13815dc086b66
4
- data.tar.gz: 1b02e5addd71a28377e73c7080ab7b88f2af28d4
3
+ metadata.gz: d0a1f7cf81639eade2bf2ac0203d87420d7b8a31
4
+ data.tar.gz: a9f5f10e11a0b00cbe9f8ae60434e0e19337f5d3
5
5
  SHA512:
6
- metadata.gz: e6317eb3c488e0590a5ffa5bae91fca369d3662555423271f5bdbf348ae93b2947a2a1b613403699a5ecf46926f4e1fe873db827b23bebe3f7b9e561d1e4472a
7
- data.tar.gz: 9b18e3a35eda7e93cdfcfb0f1566090d7eaaae81e6ceeae02b2af205edc281f9a74cfd8b2b637f3a99a43dda66c3857099e8015745039e91fa17d91e0525bd86
6
+ metadata.gz: 2a53d8b5b6e0d51912192f08d7b42a5691142976c507373996ac8c05f76dea3ccd96c77476dce6c3f4bfb82e8c0aeb47818dd618385f4a8e88081a42957deb91
7
+ data.tar.gz: cc3dc4d250b1d2eb10253b69c49f0f0d270bade569ebad3474ebd359fb1e5948b6e7b74ff0a60c4bd3b3ad0594a32839619b9bed120a3336cc496e7343619c9a
data/CHANGELOG.md CHANGED
@@ -1,7 +1,41 @@
1
1
  # Change Log
2
2
 
3
- ## [0.33.2](https://github.com/chef/inspec/tree/0.33.2) (2016-09-07)
4
- [Full Changelog](https://github.com/chef/inspec/compare/v0.33.1...0.33.2)
3
+ ## [0.34.0](https://github.com/chef/inspec/tree/0.34.0) (2016-09-12)
4
+ [Full Changelog](https://github.com/chef/inspec/compare/v0.33.2...0.34.0)
5
+
6
+ **Implemented enhancements:**
7
+
8
+ - Vendor Github and Supermarket dependencies [\#959](https://github.com/chef/inspec/issues/959)
9
+ - use simple config for security policy resource [\#1044](https://github.com/chef/inspec/pull/1044) ([chris-rock](https://github.com/chris-rock))
10
+ - identify enabled/disabled accounts for windows [\#1039](https://github.com/chef/inspec/pull/1039) ([chris-rock](https://github.com/chris-rock))
11
+
12
+ **Closed issues:**
13
+
14
+ - Compliance should allow the ability to upload the unconverted SCAP profiles from the agencies. [\#1055](https://github.com/chef/inspec/issues/1055)
15
+ - Multiple matchers in a describe block display only a single line [\#1025](https://github.com/chef/inspec/issues/1025)
16
+ - Create all content for inspec homepage demo [\#1021](https://github.com/chef/inspec/issues/1021)
17
+ - User resource should use Filtertable [\#948](https://github.com/chef/inspec/issues/948)
18
+
19
+ **Merged pull requests:**
20
+
21
+ - rename example to meta-profile [\#1051](https://github.com/chef/inspec/pull/1051) ([chris-rock](https://github.com/chris-rock))
22
+ - fix webpack start script for tutorial [\#1050](https://github.com/chef/inspec/pull/1050) ([vjeffrey](https://github.com/vjeffrey))
23
+ - Add Inspec::Fetcher\#relative\_target for compatibility [\#1046](https://github.com/chef/inspec/pull/1046) ([stevendanna](https://github.com/stevendanna))
24
+ - Typo supermarket -\> compliance [\#1041](https://github.com/chef/inspec/pull/1041) ([stevendanna](https://github.com/stevendanna))
25
+ - Improve duplicate and cycle detection in resolver [\#1038](https://github.com/chef/inspec/pull/1038) ([stevendanna](https://github.com/stevendanna))
26
+ - Add example of corporate profile [\#1037](https://github.com/chef/inspec/pull/1037) ([stevendanna](https://github.com/stevendanna))
27
+ - Ensure simplecov starts before everything else [\#1036](https://github.com/chef/inspec/pull/1036) ([stevendanna](https://github.com/stevendanna))
28
+ - add sys\_info resource to get information about the hostname [\#1035](https://github.com/chef/inspec/pull/1035) ([chris-rock](https://github.com/chris-rock))
29
+ - Add GitFetcher and rework Fetchers+SourceReaders [\#1034](https://github.com/chef/inspec/pull/1034) ([stevendanna](https://github.com/stevendanna))
30
+ - add demo content [\#1033](https://github.com/chef/inspec/pull/1033) ([vjeffrey](https://github.com/vjeffrey))
31
+ - add health graphs [\#1032](https://github.com/chef/inspec/pull/1032) ([arlimus](https://github.com/arlimus))
32
+ - fix table formatting in readme [\#1031](https://github.com/chef/inspec/pull/1031) ([arlimus](https://github.com/arlimus))
33
+ - remove old delivery tests [\#1029](https://github.com/chef/inspec/pull/1029) ([arlimus](https://github.com/arlimus))
34
+ - make demo better [\#1015](https://github.com/chef/inspec/pull/1015) ([vjeffrey](https://github.com/vjeffrey))
35
+ - user resource should support filtertable [\#990](https://github.com/chef/inspec/pull/990) ([ksubrama](https://github.com/ksubrama))
36
+
37
+ ## [v0.33.2](https://github.com/chef/inspec/tree/v0.33.2) (2016-09-07)
38
+ [Full Changelog](https://github.com/chef/inspec/compare/v0.33.1...v0.33.2)
5
39
 
6
40
  **Implemented enhancements:**
7
41
 
data/README.md CHANGED
@@ -311,6 +311,11 @@ InSpec is inspired by the wonderful [Serverspec](http://serverspec.org) project.
311
311
  1. Create new Pull Request
312
312
 
313
313
 
314
+ The InSpec community and maintainers are very active and helpful. This project benefits greatly from this activity.
315
+
316
+ [![InSpec health](https://graphs.waffle.io/chef/inspec/throughput.svg)](https://waffle.io/chef/inspec/metrics/throughput)
317
+
318
+
314
319
  ## Testing InSpec
315
320
 
316
321
  We perform `unit`, `resource` and `integration` tests.
@@ -380,21 +385,15 @@ transport:
380
385
  ```
381
386
 
382
387
 
383
- ### Chef Delivery Tests
384
-
385
- It may be informative to look at what [tests Chef Delivery](https://github.com/chef/inspec/blob/master/.delivery/build-cookbook/recipes/unit.rb) is running for CI.
386
-
387
388
  ## License
388
389
 
389
- | **Author:** | Dominik Richter (<drichter@chef.io>)
390
-
391
- | **Author:** | Christoph Hartmann (<chartmann@chef.io>)
392
-
393
- | **Copyright:** | Copyright (c) 2015 Chef Software Inc.
394
-
395
- | **Copyright:** | Copyright (c) 2015 Vulcano Security GmbH.
396
-
397
- | **License:** | Apache License, Version 2.0
390
+ | | |
391
+ | ------ | --- |
392
+ | **Author:** | Dominik Richter (<drichter@chef.io>) |
393
+ | **Author:** | Christoph Hartmann (<chartmann@chef.io>) |
394
+ | **Copyright:** | Copyright (c) 2015 Chef Software Inc. |
395
+ | **Copyright:** | Copyright (c) 2015 Vulcano Security GmbH. |
396
+ | **License:** | Apache License, Version 2.0 |
398
397
 
399
398
  Licensed under the Apache License, Version 2.0 (the "License");
400
399
  you may not use this file except in compliance with the License.
@@ -0,0 +1,11 @@
1
+ # meta-profile
2
+
3
+ The inspec.yml file in this profile shows how one can use dependencies
4
+ from non-local sources such as Git or an HTTP url. This feature can
5
+ be used to build up a environment-wide profile that is based on more
6
+ specific profiles managed by others.
7
+
8
+ # WARNING
9
+
10
+ This profile likely does not work yet. It exists as a target for
11
+ ongoing development work.
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ # copyright: 2015, The Authors
3
+ # license: All rights reserved
4
+ include_controls 'ssh-hardening'
5
+ include_controls 'os-hardening'
6
+ include_controls 'ssl-benchmark'
7
+ include_controls 'linux'
8
+ include_controls 'windows-patch-benchmark'
@@ -0,0 +1,19 @@
1
+ name: meta-profile
2
+ title: Meta Compliance Profile
3
+ maintainer: InSpec Authors
4
+ copyright: InSpec Authors
5
+ copyright_email: support@chef.io
6
+ license: Apache 2
7
+ summary: InSpec Profile that is only consuming dependencies
8
+ version: 0.2.0
9
+ depends:
10
+ - name: ssh-hardening
11
+ supermarket: hardening/ssh-hardening
12
+ - name: os-hardening
13
+ url: https://github.com/dev-sec/tests-os-hardening/archive/master.zip
14
+ - name: ssl-benchmark
15
+ git: https://github.com/dev-sec/ssl-benchmark.git
16
+ - name: windows-patch-benchmark
17
+ git: https://github.com/chris-rock/windows-patch-benchmark.git
18
+ - name: linux
19
+ compliance: base/linux
@@ -4,7 +4,6 @@
4
4
 
5
5
  require 'uri'
6
6
  require 'inspec/fetcher'
7
- require 'fetchers/url'
8
7
 
9
8
  # InSpec Target Helper for Chef Compliance
10
9
  # reuses UrlHelper, but it knows the target server and the access token already
@@ -14,11 +13,14 @@ module Compliance
14
13
  name 'compliance'
15
14
  priority 500
16
15
 
17
- def self.resolve(target, _opts = {})
18
- return nil unless target.is_a?(String)
19
- # check for local scheme compliance://
20
- uri = URI(target)
21
- return nil unless URI(uri).scheme == 'compliance'
16
+ def self.resolve(target)
17
+ uri = if target.is_a?(String) && URI(target).scheme == 'compliance'
18
+ URI(target)
19
+ elsif target.respond_to?(:key?) && target.key?(:compliance)
20
+ URI("compliance://#{target[:compliance]}")
21
+ end
22
+
23
+ return nil if uri.nil?
22
24
 
23
25
  # check if we have a compliance token
24
26
  config = Compliance::Configuration.new
@@ -27,18 +29,33 @@ module Compliance
27
29
  # verifies that the target e.g base/ssh exists
28
30
  profile = uri.host + uri.path
29
31
  Compliance::API.exist?(config, profile)
30
- super(target_url(config, profile), config)
32
+ new(target_url(profile, config), config)
31
33
  rescue URI::Error => _e
32
34
  nil
33
35
  end
34
36
 
35
- def self.target_url(config, profile)
37
+ def self.target_url(profile, config)
36
38
  owner, id = profile.split('/')
37
39
  "#{config['server']}/owners/#{owner}/compliance/#{id}/tar"
38
40
  end
39
41
 
42
+ #
43
+ # We want to save compliance: in the lockfile rather than url: to
44
+ # make sure we go back through the ComplianceAPI handling.
45
+ #
46
+ def resolved_source
47
+ { compliance: supermarket_profile_name }
48
+ end
49
+
40
50
  def to_s
41
51
  'Chef Compliance Profile Loader'
42
52
  end
53
+
54
+ private
55
+
56
+ def supermarket_profile_name
57
+ m = %r{^#{@config['server']}/owners/(?<owner>[^/]+)/compliance/(?<id>[^/]+)/tar$}.match(@target)
58
+ "#{m[:owner]}/#{m[:id]}"
59
+ end
43
60
  end
44
61
  end
@@ -9,18 +9,14 @@ module Supermarket
9
9
  class API
10
10
  SUPERMARKET_URL = 'https://supermarket.chef.io'.freeze
11
11
 
12
- def self.supermarket_url
13
- SUPERMARKET_URL
14
- end
15
-
16
12
  # displays a list of profiles
17
- def self.profiles
18
- url = "#{SUPERMARKET_URL}/api/v1/tools-search"
13
+ def self.profiles(supermarket_url = SUPERMARKET_URL)
14
+ url = "#{supermarket_url}/api/v1/tools-search"
19
15
  _success, data = get(url, { q: 'compliance_profile' })
20
16
  if !data.nil?
21
17
  profiles = JSON.parse(data)
22
18
  profiles['items'].map { |x|
23
- m = %r{^#{Supermarket::API.supermarket_url}/api/v1/tools/(?<slug>[\w-]+)(/)?$}.match(x['tool'])
19
+ m = %r{^#{supermarket_url}/api/v1/tools/(?<slug>[\w-]+)(/)?$}.match(x['tool'])
24
20
  x['slug'] = m[:slug]
25
21
  x
26
22
  }
@@ -37,10 +33,10 @@ module Supermarket
37
33
  end
38
34
 
39
35
  # displays profile infos
40
- def self.info(profile)
36
+ def self.info(profile, supermarket_url = SUPERMARKET_URL)
41
37
  _tool_owner, tool_name = profile_name("supermarket://#{profile}")
42
38
  return if tool_name.nil? || tool_name.empty?
43
- url = "#{SUPERMARKET_URL}/api/v1/tools/#{tool_name}"
39
+ url = "#{supermarket_url}/api/v1/tools/#{tool_name}"
44
40
  _success, data = get(url, {})
45
41
  JSON.parse(data) if !data.nil?
46
42
  rescue JSON::ParserError
@@ -48,24 +44,24 @@ module Supermarket
48
44
  end
49
45
 
50
46
  # compares a profile with the supermarket tool info
51
- def self.same?(profile, supermarket_tool)
47
+ def self.same?(profile, supermarket_tool, supermarket_url = SUPERMARKET_URL)
52
48
  tool_owner, tool_name = profile_name(profile)
53
- tool = "#{SUPERMARKET_URL}/api/v1/tools/#{tool_name}"
49
+ tool = "#{supermarket_url}/api/v1/tools/#{tool_name}"
54
50
  supermarket_tool['tool_owner'] == tool_owner && supermarket_tool['tool'] == tool
55
51
  end
56
52
 
57
- def self.find(profile)
58
- profiles = Supermarket::API.profiles
53
+ def self.find(profile, supermarket_url)
54
+ profiles = Supermarket::API.profiles(supermarket_url=SUPERMARKET_URL)
59
55
  if !profiles.empty?
60
- index = profiles.index { |t| same?(profile, t) }
56
+ index = profiles.index { |t| same?(profile, t, supermarket_url) }
61
57
  # return profile or nil
62
58
  profiles[index] if !index.nil? && index >= 0
63
59
  end
64
60
  end
65
61
 
66
62
  # verifies that a profile exists
67
- def self.exist?(profile)
68
- !find(profile).nil?
63
+ def self.exist?(profile, supermarket_url = SUPERMARKET_URL)
64
+ !find(profile, supermarket_url).nil?
69
65
  end
70
66
 
71
67
  def self.get(url, params)
@@ -8,16 +8,21 @@ require 'fetchers/url'
8
8
 
9
9
  # InSpec Target Helper for Supermarket
10
10
  module Supermarket
11
- class Fetcher < Fetchers::Url
11
+ class Fetcher < Inspec.fetcher(1)
12
12
  name 'supermarket'
13
13
  priority 500
14
14
 
15
15
  def self.resolve(target, opts = {})
16
- return nil unless target.is_a?(String)
17
- return nil unless URI(target).scheme == 'supermarket'
18
- return nil unless Supermarket::API.exist?(target)
19
- tool_info = Supermarket::API.find(target)
20
- super(tool_info['tool_source_url'], opts)
16
+ supermarket_uri, supermarket_server = if target.is_a?(String) && URI(target).scheme == 'supermarket'
17
+ [target, Supermarket::API::SUPERMARKET_URL]
18
+ elsif target.respond_to?(:key?) && target.key?(:supermarket)
19
+ supermarket_server = target[:supermarket_url] || Supermarket::API::SUPERMARKET_URL
20
+ ["supermarket://#{target[:supermarket]}", supermarket_server]
21
+ end
22
+ return nil unless supermarket_uri
23
+ return nil unless Supermarket::API.exist?(supermarket_uri, supermarket_server)
24
+ tool_info = Supermarket::API.find(supermarket_uri, supermarket_server)
25
+ resolve_next(tool_info['tool_source_url'], opts)
21
26
  rescue URI::Error
22
27
  nil
23
28
  end
@@ -0,0 +1,162 @@
1
+ # encoding: utf-8
2
+ require 'tmpdir'
3
+ require 'fileutils'
4
+ require 'mixlib/shellout'
5
+ require 'inspec/log'
6
+
7
+ module Fetchers
8
+ #
9
+ # The git fetcher uses the git binary to fetch remote git sources.
10
+ # Git-based sources should be specified with the `git:` key in the
11
+ # source hash. Additionally, we accept `:branch`, `:ref`, and `:tag`
12
+ # keys to allow users to pin to a particular revision.
13
+ #
14
+ # Parts of this class are derived from:
15
+ #
16
+ # https://github.com/chef/omnibus/blob/master/lib/omnibus/fetchers/git_fetcher.rb
17
+ #
18
+ # which is Copyright 2012-2014 Chef Software, Inc. and offered under
19
+ # the same Apache 2 software license as inspec.
20
+ #
21
+ # Many thanks to the omnibus authors!
22
+ #
23
+ # Note that we haven't replicated all of omnibus' features here. If
24
+ # you got to this file during debugging, you may want to look at the
25
+ # omnibus source for hints.
26
+ #
27
+ class Git < Inspec.fetcher(1)
28
+ name 'git'
29
+ priority 200
30
+
31
+ def self.resolve(target, opts = {})
32
+ if target.respond_to?(:has_key?) &&target.key?(:git)
33
+ new(target[:git], opts.merge(target))
34
+ end
35
+ end
36
+
37
+ def initialize(remote_url, opts = {})
38
+ @branch = opts[:branch]
39
+ @tag = opts[:tag]
40
+ @ref = opts[:ref]
41
+ @remote_url = remote_url
42
+ @repo_directory = nil
43
+ end
44
+
45
+ def fetch(dir)
46
+ @repo_directory = dir
47
+ if cloned?
48
+ checkout
49
+ else
50
+ Dir.mktmpdir do |tmpdir|
51
+ checkout(tmpdir)
52
+ Inspec::Log.debug("Checkout of #{resolved_ref} successful. Moving checkout to #{dir}")
53
+ FileUtils.cp_r(tmpdir, @repo_directory)
54
+ end
55
+ end
56
+ @repo_directory
57
+ end
58
+
59
+ def archive_path
60
+ @repo_directory
61
+ end
62
+
63
+ def resolved_source
64
+ { git: @remote_url, ref: resolved_ref }
65
+ end
66
+
67
+ private
68
+
69
+ def resolved_ref
70
+ @resolved_ref ||= if @ref
71
+ @ref
72
+ elsif @branch
73
+ resolve_ref(@branch)
74
+ elsif @tag
75
+ resolve_ref(@tag)
76
+ else
77
+ resolve_ref('master')
78
+ end
79
+ end
80
+
81
+ def resolve_ref(ref_name)
82
+ cmd = shellout("git ls-remote \"#{@remote_url}\" \"#{ref_name}*\"")
83
+ ref = parse_ls_remote(cmd.stdout, ref_name)
84
+ if !ref
85
+ fail "Unable to resolve #{ref_name} to a specific git commit for #{@remote_url}"
86
+ end
87
+ ref
88
+ end
89
+
90
+ #
91
+ # The following comment is a minor modification of the comment in
92
+ # the omnibus source for a similar function:
93
+ #
94
+ # Dereference annotated tags.
95
+ #
96
+ # The +remote_list+ parameter is assumed to look like this:
97
+ #
98
+ # a2ed66c01f42514bcab77fd628149eccb4ecee28 refs/tags/rel-0.11.0
99
+ # f915286abdbc1907878376cce9222ac0b08b12b8 refs/tags/rel-0.11.0^{}
100
+ #
101
+ # The SHA with ^{} is the commit pointed to by an annotated
102
+ # tag. If ref isn't an annotated tag, there will not be a line
103
+ # with trailing ^{}.
104
+ #
105
+ # @param [String] output
106
+ # output from `git ls-remote origin` command
107
+ # @param [String] ref_name
108
+ # the target git ref_name
109
+ #
110
+ # @return [String]
111
+ #
112
+ def parse_ls_remote(output, ref_name)
113
+ pairs = output.lines.map { |l| l.chomp.split("\t") }
114
+ tagged_commit = pairs.find { |m| m[1].end_with?("#{ref_name}^{}") }
115
+ if tagged_commit
116
+ tagged_commit.first
117
+ else
118
+ found = pairs.find { |m| m[1].end_with?(ref_name.to_s) }
119
+ if found
120
+ found.first
121
+ end
122
+ end
123
+ end
124
+
125
+ def cloned?
126
+ File.directory?(File.join(@repo_directory, '.git'))
127
+ end
128
+
129
+ def clone(dir = @repo_directory)
130
+ git_cmd("clone #{@remote_url} ./", dir) unless cloned?
131
+ @repo_directory
132
+ end
133
+
134
+ def checkout(dir = @repo_directory)
135
+ clone(dir)
136
+ git_cmd("checkout #{resolved_ref}", dir)
137
+ @repo_directory
138
+ end
139
+
140
+ def git_cmd(cmd, dir = @repo_directory)
141
+ cmd = shellout("git #{cmd}", cwd: dir)
142
+ cmd.error!
143
+ cmd.status
144
+ rescue Errno::ENOENT
145
+ raise 'To use git sources, you must have git installed.'
146
+ end
147
+
148
+ def shellout(cmd, opts = {})
149
+ Inspec::Log.debug("Running external command: #{cmd} (#{opts})")
150
+ cmd = Mixlib::ShellOut.new(cmd, opts)
151
+ cmd.run_command
152
+ Inspec::Log.debug("External command: completed with exit status: #{cmd.exitstatus}")
153
+ Inspec::Log.debug('External command: STDOUT BEGIN')
154
+ Inspec::Log.debug(cmd.stdout)
155
+ Inspec::Log.debug('External command: STDOUT END')
156
+ Inspec::Log.debug('External command: STDERR BEGIN')
157
+ Inspec::Log.debug(cmd.stderr)
158
+ Inspec::Log.debug('External command: STDERR END')
159
+ cmd
160
+ end
161
+ end
162
+ end
@@ -7,11 +7,29 @@ module Fetchers
7
7
  name 'local'
8
8
  priority 0
9
9
 
10
- attr_reader :files
11
-
12
10
  def self.resolve(target)
13
- return nil unless target.is_a?(String)
11
+ local_path = if target.is_a?(String)
12
+ resolve_from_string(target)
13
+ elsif target.is_a?(Hash)
14
+ resolve_from_hash(target)
15
+ end
16
+
17
+ if local_path
18
+ new(local_path)
19
+ end
20
+ end
21
+
22
+ def self.resolve_from_hash(target)
23
+ if target.key?(:path)
24
+ local_path = target[:path]
25
+ if target.key?(:cwd)
26
+ local_path = File.expand_path(local_path, target[:cwd])
27
+ end
28
+ local_path
29
+ end
30
+ end
14
31
 
32
+ def self.resolve_from_string(target)
15
33
  # Support "urls" in the form of file://
16
34
  if target.start_with?('file://')
17
35
  target = target.gsub(%r{^file://}, '')
@@ -20,26 +38,25 @@ module Fetchers
20
38
  target = target.tr('\\', '/')
21
39
  end
22
40
 
23
- if !File.exist?(target)
24
- nil
25
- else
26
- new(target)
41
+ if File.exist?(target)
42
+ target
27
43
  end
28
44
  end
29
45
 
30
46
  def initialize(target)
31
47
  @target = target
32
- if File.file?(target)
33
- @files = [target]
34
- else
35
- @files = Dir[File.join(target, '**', '*')]
36
- end
37
48
  end
38
49
 
39
- def read(file)
40
- return nil unless files.include?(file)
41
- return nil unless File.file?(file)
42
- File.read(file)
50
+ def fetch(_path)
51
+ archive_path
52
+ end
53
+
54
+ def archive_path
55
+ @target
56
+ end
57
+
58
+ def resolved_source
59
+ { path: @target }
43
60
  end
44
61
  end
45
62
  end
data/lib/fetchers/mock.rb CHANGED
@@ -16,12 +16,16 @@ module Fetchers
16
16
  @data = data
17
17
  end
18
18
 
19
- def files
20
- @data.keys
19
+ def fetch(_path)
20
+ archive_path
21
21
  end
22
22
 
23
- def read(file)
24
- @data[file]
23
+ def archive_path
24
+ { mock: @data }
25
+ end
26
+
27
+ def resolved_source
28
+ { mock_fetcher: true }
25
29
  end
26
30
  end
27
31
  end