Sperate hook for authenticating url and adding headers for authentication
This commit is contained in:
parent
f440012b30
commit
0d1635303f
@ -76,8 +76,18 @@ module Vagrant
|
||||
end
|
||||
end
|
||||
|
||||
# Call the hook to transform URLs into authenticated URLs.
|
||||
# In the case we don't have a plugin that does this, then it
|
||||
# will just return the same URLs.
|
||||
hook_env = env[:hook].call(
|
||||
:authenticate_box_url, box_urls: url.dup)
|
||||
authed_urls = hook_env[:box_urls]
|
||||
if !authed_urls || authed_urls.length != url.length
|
||||
raise "Bad box authentication hook, did not generate proper results."
|
||||
end
|
||||
|
||||
# Test if any of our URLs point to metadata
|
||||
is_metadata_results = url.map do |u|
|
||||
is_metadata_results = authed_urls.map do |u|
|
||||
begin
|
||||
metadata_url?(u, env)
|
||||
rescue Errors::DownloaderError => e
|
||||
@ -105,7 +115,8 @@ module Vagrant
|
||||
end
|
||||
|
||||
if is_metadata
|
||||
add_from_metadata(url.first, env, expanded)
|
||||
url = [url.first, authed_urls.first]
|
||||
add_from_metadata(url, env, expanded)
|
||||
else
|
||||
add_direct(url, env)
|
||||
end
|
||||
@ -147,7 +158,10 @@ module Vagrant
|
||||
|
||||
# Adds a box given that the URL is a metadata document.
|
||||
#
|
||||
# @param [String] url The URL of the metadata for the box to add.
|
||||
# @param [String | Array<String>] url The URL of the metadata for
|
||||
# the box to add. If this is an array, then it must be a two-element
|
||||
# array where the first element is the original URL and the second
|
||||
# element is an authenticated URL.
|
||||
# @param [Hash] env
|
||||
# @param [Bool] expanded True if the metadata URL was expanded with
|
||||
# a Atlas server URL.
|
||||
@ -156,6 +170,15 @@ module Vagrant
|
||||
provider = env[:box_provider]
|
||||
provider = Array(provider) if provider
|
||||
version = env[:box_version]
|
||||
|
||||
authenticated_url = url
|
||||
if url.is_a?(Array)
|
||||
# We have both a normal URL and "authenticated" URL. Split
|
||||
# them up.
|
||||
authenticated_url = url[1]
|
||||
url = url[0]
|
||||
end
|
||||
|
||||
display_original_url = Util::CredentialScrubber.scrub(Array(original_url).first)
|
||||
display_url = Util::CredentialScrubber.scrub(url)
|
||||
|
||||
@ -170,7 +193,7 @@ module Vagrant
|
||||
metadata = nil
|
||||
begin
|
||||
metadata_path = download(
|
||||
url, env, json: true, ui: false)
|
||||
authenticated_url, env, json: true, ui: false)
|
||||
return if @download_interrupted
|
||||
|
||||
File.open(metadata_path) do |f|
|
||||
@ -248,6 +271,16 @@ module Vagrant
|
||||
end
|
||||
|
||||
provider_url = metadata_provider.url
|
||||
if provider_url != authenticated_url
|
||||
# Authenticate the provider URL since we're using auth
|
||||
hook_env = env[:hook].call(:authenticate_box_url, box_urls: [provider_url])
|
||||
authed_urls = hook_env[:box_urls]
|
||||
if !authed_urls || authed_urls.length != 1
|
||||
raise "Bad box authentication hook, did not generate proper results."
|
||||
end
|
||||
provider_url = authed_urls[0]
|
||||
end
|
||||
|
||||
box_add(
|
||||
[[provider_url, metadata_provider.url]],
|
||||
metadata.name,
|
||||
@ -404,7 +437,7 @@ module Vagrant
|
||||
downloader_options[:box_extra_download_options] = env[:box_extra_download_options]
|
||||
|
||||
d = Util::Downloader.new(url, temp_path, downloader_options)
|
||||
env[:hook].call(:authenticate_box_url, downloader: d)
|
||||
env[:hook].call(:authenticate_box_downloader, downloader: d)
|
||||
d
|
||||
end
|
||||
|
||||
@ -412,7 +445,7 @@ module Vagrant
|
||||
opts[:ui] = true if !opts.key?(:ui)
|
||||
|
||||
d = downloader(url, env, **opts)
|
||||
env[:hook].call(:authenticate_box_url, downloader: d)
|
||||
env[:hook].call(:authenticate_box_downloader, downloader: d)
|
||||
|
||||
# Download the box to a temporary path. We store the temporary
|
||||
# path as an instance variable so that the `#recover` method can
|
||||
@ -456,7 +489,7 @@ module Vagrant
|
||||
# @return [Boolean] true if metadata
|
||||
def metadata_url?(url, env)
|
||||
d = downloader(url, env, json: true, ui: false)
|
||||
env[:hook].call(:authenticate_box_url, downloader: d)
|
||||
env[:hook].call(:authenticate_box_downloader, downloader: d)
|
||||
|
||||
# If we're downloading a file, cURL just returns no
|
||||
# content-type (makes sense), so we just test if it is JSON
|
||||
|
||||
@ -136,7 +136,7 @@ module Vagrant
|
||||
opts = { headers: ["Accept: application/json"] }.merge(download_options)
|
||||
d = Util::Downloader.new(url, tf.path, opts)
|
||||
if @hook
|
||||
@hook.call(:authenticate_box_url, downloader: d)
|
||||
@hook.call(:authenticate_box_downloader, downloader: d)
|
||||
end
|
||||
d.download!
|
||||
BoxMetadata.new(File.open(tf.path, "r"))
|
||||
|
||||
@ -317,6 +317,12 @@ module Vagrant
|
||||
metadata_url_file = box_directory.join("metadata_url")
|
||||
metadata_url = metadata_url_file.read if metadata_url_file.file?
|
||||
|
||||
if metadata_url && @hook
|
||||
hook_env = @hook.call(
|
||||
:authenticate_box_url, box_urls: [metadata_url])
|
||||
metadata_url = hook_env[:box_urls].first
|
||||
end
|
||||
|
||||
return Box.new(
|
||||
name, provider, version_dir_map[v.to_s], provider_dir,
|
||||
metadata_url: metadata_url, hook: @hook
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
require "cgi"
|
||||
require "uri"
|
||||
|
||||
require "vagrant/util/credential_scrubber"
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/client/client")
|
||||
|
||||
module VagrantPlugins
|
||||
@ -35,34 +33,47 @@ module VagrantPlugins
|
||||
def call(env)
|
||||
client = Client.new(env[:env])
|
||||
token = client.token
|
||||
target_url = URI.parse(env[:downloader].source)
|
||||
Vagrant::Util::CredentialScrubber.sensitive(token)
|
||||
|
||||
if target_url.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(target_url.host)
|
||||
env[:box_urls].map! do |url|
|
||||
begin
|
||||
target_url.host = TARGET_HOST
|
||||
target_url = target_url.to_s
|
||||
u = URI.parse(url)
|
||||
if u.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(u.host)
|
||||
u.host = TARGET_HOST
|
||||
u.to_s
|
||||
else
|
||||
url
|
||||
end
|
||||
rescue URI::Error
|
||||
# if there is an error, use current target_url
|
||||
url
|
||||
end
|
||||
end
|
||||
|
||||
server_uri = URI.parse(Vagrant.server_url.to_s)
|
||||
|
||||
if token && !server_uri.host.to_s.empty?
|
||||
if target_url.host == server_uri.host
|
||||
if server_uri.host != TARGET_HOST && !self.class.custom_host_notified?
|
||||
env[:ui].warn(I18n.t("cloud_command.middleware.authentication.different_target",
|
||||
custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
|
||||
sleep CUSTOM_HOST_NOTIFY_WAIT
|
||||
self.class.custom_host_notified!
|
||||
env[:box_urls].map! do |url|
|
||||
u = URI.parse(url)
|
||||
|
||||
if u.host == server_uri.host
|
||||
if server_uri.host != TARGET_HOST && !self.class.custom_host_notified?
|
||||
env[:ui].warn(I18n.t("cloud_command.middleware.authentication.different_target",
|
||||
custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
|
||||
sleep CUSTOM_HOST_NOTIFY_WAIT
|
||||
self.class.custom_host_notified!
|
||||
end
|
||||
|
||||
q = CGI.parse(u.query || "")
|
||||
|
||||
current = q["access_token"]
|
||||
if current && current.empty?
|
||||
q["access_token"] = token
|
||||
end
|
||||
|
||||
u.query = URI.encode_www_form(q)
|
||||
end
|
||||
|
||||
if env[:downloader].headers && !env[:downloader].headers.any? { |h| h.include?("Authorization") }
|
||||
env[:downloader].headers << "Authorization: Bearer #{token}"
|
||||
end
|
||||
u.to_s
|
||||
end
|
||||
|
||||
env[:downloader]
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
require "cgi"
|
||||
require "uri"
|
||||
|
||||
require "vagrant/util/credential_scrubber"
|
||||
require_relative "./add_authentication"
|
||||
|
||||
require Vagrant.source_root.join("plugins/commands/cloud/client/client")
|
||||
|
||||
module VagrantPlugins
|
||||
module CloudCommand
|
||||
class AddDownloaderAuthentication < AddAuthentication
|
||||
|
||||
def call(env)
|
||||
client = Client.new(env[:env])
|
||||
token = client.token
|
||||
target_url = URI.parse(env[:downloader].source)
|
||||
Vagrant::Util::CredentialScrubber.sensitive(token)
|
||||
|
||||
if target_url.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(target_url.host)
|
||||
begin
|
||||
target_url.host = TARGET_HOST
|
||||
target_url = target_url.to_s
|
||||
rescue URI::Error
|
||||
# if there is an error, use current target_url
|
||||
end
|
||||
end
|
||||
|
||||
server_uri = URI.parse(Vagrant.server_url.to_s)
|
||||
if token && !server_uri.host.to_s.empty?
|
||||
if target_url.host == server_uri.host
|
||||
if server_uri.host != TARGET_HOST && !self.class.custom_host_notified?
|
||||
env[:ui].warn(I18n.t("cloud_command.middleware.authentication.different_target",
|
||||
custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
|
||||
sleep CUSTOM_HOST_NOTIFY_WAIT
|
||||
self.class.custom_host_notified!
|
||||
end
|
||||
|
||||
if env[:downloader].headers && !env[:downloader].headers.any? { |h| h.include?("Authorization") }
|
||||
env[:downloader].headers << "Authorization: Bearer #{token}"
|
||||
end
|
||||
end
|
||||
|
||||
env[:downloader]
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
end.freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -22,6 +22,11 @@ module VagrantPlugins
|
||||
hook.prepend(AddAuthentication)
|
||||
end
|
||||
|
||||
action_hook(:cloud_authenticated_boxes, :authenticate_box_downloader) do |hook|
|
||||
require_relative "auth/middleware/add_downloader_authentication"
|
||||
hook.prepend(AddDownloaderAuthentication)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def self.init!
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user