Class: Inspec::Fetcher::Url

Inherits:
Object
  • Object
show all
Defined in:
lib/inspec/fetcher/url.rb

Direct Known Subclasses

InspecPlugins::Compliance::Fetcher

Constant Summary collapse

MIME_TYPES =
{
  "application/x-zip-compressed" => ".zip",
  "application/zip" => ".zip",
  "application/x-gzip" => ".tar.gz",
  "application/gzip" => ".tar.gz",
}.freeze
GITHUB_URL_REGEX =
%r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w.-]+?)(\.git)?(/)?$}.freeze
GITHUB_URL_WITH_TREE_REGEX =
%r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w.-]+)/tree/(?<commit>[\w\.]+)(/)?$}.freeze
BITBUCKET_URL_REGEX =
%r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)(\.git)?(/)?$}.freeze
BITBUCKET_URL_BRANCH_REGEX =
%r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/branch/(?<branch>[\w\.]+)(/)?$}.freeze
BITBUCKET_URL_COMMIT_REGEX =
%r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/commits/(?<commit>[\w\.]+)(/)?$}.freeze
GITHUB_URL =
"https://github.com".freeze
BITBUCKET_URL =
"https://bitbucket.org".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, opts) ⇒ Url

Returns a new instance of Url.



105
106
107
108
109
110
111
112
113
# File 'lib/inspec/fetcher/url.rb', line 105

def initialize(url, opts)
  @target = url.to_s
  @target_uri = url.is_a?(URI) ? url : parse_uri(url)
  @insecure = opts["insecure"]
  @token = opts["token"]
  @config = opts
  @archive_path = nil
  @temp_archive_path = nil
end

Instance Attribute Details

#archive_pathObject (readonly)

Returns the value of attribute archive_path.



103
104
105
# File 'lib/inspec/fetcher/url.rb', line 103

def archive_path
  @archive_path
end

#filesObject (readonly)

Returns the value of attribute files.



103
104
105
# File 'lib/inspec/fetcher/url.rb', line 103

def files
  @files
end

Class Method Details

.default_ref(match_data, repo_url) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/inspec/fetcher/url.rb', line 134

def default_ref(match_data, repo_url)
  remote_url = "#{repo_url}/#{match_data[:user]}/#{match_data[:repo]}.git"
  command_string = "git remote show #{remote_url}"
  cmd = shellout(command_string)
  unless cmd.exitstatus == 0
    raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{remote_url} - error running '#{command_string}': #{cmd.stderr}")
  else
    ref = cmd.stdout.lines.detect { |l| l.include? "HEAD branch:" }&.split(":")&.last&.strip
    unless ref
      raise(Inspec::FetcherFailure, "Profile git dependency failed with default reference - #{remote_url} - error running '#{command_string}': NULL reference")
    end

    ref
  end
end

.resolve(target, opts = {}) ⇒ Object



18
19
20
21
22
23
24
25
26
# File 'lib/inspec/fetcher/url.rb', line 18

def self.resolve(target, opts = {})
  if target.is_a?(Hash) && target.key?(:url)
    resolve_from_string(target[:url], opts, target[:username], target[:password])
  elsif target.is_a?(String)
    resolve_from_string(target, opts)
  elsif target.is_a?(URI)
    resolve_from_string(target.to_s, opts)
  end
end

.resolve_from_string(target, opts, username = nil, password = nil) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/inspec/fetcher/url.rb', line 28

def self.resolve_from_string(target, opts, username = nil, password = nil)
  uri = URI.parse(target)
  return nil if uri.nil? || uri.scheme.nil?
  return nil unless %{ http https }.include? uri.scheme

  target = transform(target)
  opts[:username] = username if username
  opts[:password] = password if password
  new(target, opts)
rescue URI::Error
  nil
end

.shellout(cmd, opts = {}) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/inspec/fetcher/url.rb', line 150

def shellout(cmd, opts = {})
  Inspec::Log.debug("Running external command: #{cmd} (#{opts})")
  cmd = Mixlib::ShellOut.new(cmd, opts)
  cmd.run_command
  Inspec::Log.debug("External command: completed with exit status: #{cmd.exitstatus}")
  Inspec::Log.debug("External command: STDOUT BEGIN")
  Inspec::Log.debug(cmd.stdout)
  Inspec::Log.debug("External command: STDOUT END")
  Inspec::Log.debug("External command: STDERR BEGIN")
  Inspec::Log.debug(cmd.stderr)
  Inspec::Log.debug("External command: STDERR END")
  cmd
end

.transform(target) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/inspec/fetcher/url.rb', line 80

def self.transform(target)
  transformed_target = if m = GITHUB_URL_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
                         default_branch = default_ref(m, GITHUB_URL)
                         "https://github.com/#{m[:user]}/#{m[:repo]}/archive/#{default_branch}.tar.gz"
                       elsif m = GITHUB_URL_WITH_TREE_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
                         "https://github.com/#{m[:user]}/#{m[:repo]}/archive/#{m[:commit]}.tar.gz"
                       elsif m = BITBUCKET_URL_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
                         default_branch = default_ref(m, BITBUCKET_URL)
                         "https://bitbucket.org/#{m[:user]}/#{m[:repo]}/get/#{default_branch}.tar.gz"
                       elsif m = BITBUCKET_URL_BRANCH_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
                         "https://bitbucket.org/#{m[:user]}/#{m[:repo]}/get/#{m[:branch]}.tar.gz"
                       elsif m = BITBUCKET_URL_COMMIT_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
                         "https://bitbucket.org/#{m[:user]}/#{m[:repo]}/get/#{m[:commit]}.tar.gz"
                       end

  if transformed_target
    Inspec::Log.warn("URL target #{target} transformed to #{transformed_target}. Consider using the git fetcher")
    transformed_target
  else
    target
  end
end

Instance Method Details

#cache_keyObject



123
124
125
# File 'lib/inspec/fetcher/url.rb', line 123

def cache_key
  @archive_shasum ||= sha256
end

#fetch(path) ⇒ Object



115
116
117
# File 'lib/inspec/fetcher/url.rb', line 115

def fetch(path)
  @archive_path ||= download_archive(path)
end

#resolved_sourceObject



119
120
121
# File 'lib/inspec/fetcher/url.rb', line 119

def resolved_source
  @resolved_source ||= { url: @target, sha256: sha256 }
end

#to_sObject



127
128
129
# File 'lib/inspec/fetcher/url.rb', line 127

def to_s
  @target
end