Update behavior of the authentication middleware

Always remap old hosts to target host when encountered. When custom
vagrant server is defined, warn when tokens may be attached and allow
time for user to cancel.

Fixes #9442
This commit is contained in:
Chris Roberts 2018-02-21 17:00:58 -08:00
parent 1cc4a48371
commit f2bf18e56b
4 changed files with 80 additions and 24 deletions

View File

@ -10,7 +10,7 @@ module Vagrant
# of Vagrant that may require remote access.
#
# @return [String]
DEFAULT_SERVER_URL = "https://vagrantcloud.com"
DEFAULT_SERVER_URL = "https://vagrantcloud.com".freeze
# Max number of seconds to wait for joining an active thread.
#

View File

@ -1,5 +1,17 @@
en:
login_command:
middleware:
authentication:
different_target: |-
Vagrant has detected a custom Vagrant server in use for downloading
box files. An authentication token is currently set which will be
added to the box request. If the custom Vagrant server should not
be receiving the authentication token, please unset it.
Known Vagrant server: %{known_host}
Custom Vagrant server: %{custom_host}
Press ctrl-c to cancel...
errors:
server_error: |-
The Vagrant Cloud server responded with a not-OK response:

View File

@ -6,35 +6,43 @@ require_relative "../client"
module VagrantPlugins
module LoginCommand
class AddAuthentication
ALLOWED_AUTHENTICATION_HOSTS = %w[
app.vagrantup.com
atlas.hashicorp.com
vagrantcloud.com
REPLACEMENT_HOSTS = [
"app.vagrantup.com".freeze,
"atlas.hashicorp.com".freeze
].freeze
TARGET_HOST = "vagrantcloud.com".freeze
CUSTOM_HOST_NOTIFY_WAIT = 5
def initialize(app, env)
@app = app
LoginCommand::Plugin.init!
end
def call(env)
client = Client.new(env[:env])
token = client.token
if token && Vagrant.server_url
server_uri = URI.parse(Vagrant.server_url)
env[:box_urls].map! do |url|
u = URI.parse(url)
if u.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(u.host)
u.host = TARGET_HOST
end
u.to_s
end
server_uri = URI.parse(Vagrant.server_url.to_s)
if token && !server_uri.host.to_s.empty?
if server_uri.host != TARGET_HOST
env[:ui].warn(I18n.t("login_command.middleware.authentication.different_target",
custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
sleep CUSTOM_HOST_NOTIFY_WAIT
end
env[:box_urls].map! do |url|
u = URI.parse(url)
replace = u.host == server_uri.host
if !replace
if ALLOWED_AUTHENTICATION_HOSTS.include?(u.host) &&
ALLOWED_AUTHENTICATION_HOSTS.include?(server_uri.host)
replace = true
end
end
if replace
if u.host == server_uri.host
q = CGI.parse(u.query || "")
current = q["access_token"]
@ -50,7 +58,7 @@ module VagrantPlugins
end
@app.call(env)
end
end.freeze
end
end
end

View File

@ -6,17 +6,20 @@ describe VagrantPlugins::LoginCommand::AddAuthentication do
include_context "unit"
let(:app) { lambda { |env| } }
let(:ui) { double("ui") }
let(:env) { {
env: iso_env,
ui: ui
} }
let(:iso_env) { isolated_environment.create_vagrant_env }
let(:server_url) { "http://foo.com" }
let(:server_url) { "http://vagrantcloud.com" }
subject { described_class.new(app, env) }
before do
allow(Vagrant).to receive(:server_url).and_return(server_url)
allow(ui).to receive(:warn)
stub_env("ATLAS_TOKEN" => nil)
end
@ -62,24 +65,46 @@ describe VagrantPlugins::LoginCommand::AddAuthentication do
expect(env[:box_urls]).to eq(expected)
end
it "appends the access token to vagrantcloud.com URLs if Atlas" do
it "does not append the access token to vagrantcloud.com URLs if Atlas" do
server_url = "https://atlas.hashicorp.com"
allow(Vagrant).to receive(:server_url).and_return(server_url)
allow(subject).to receive(:sleep)
token = "foobarbaz"
VagrantPlugins::LoginCommand::Client.new(iso_env).store_token(token)
original = [
"http://google.com/box.box",
"http://vagrantcloud.com/foo.box",
"http://vagrantcloud.com/bar.box?arg=true",
]
expected = original.dup
env[:box_urls] = original.dup
subject.call(env)
expect(env[:box_urls]).to eq(expected)
end
it "warns when adding token to custom server" do
server_url = "https://example.com"
allow(Vagrant).to receive(:server_url).and_return(server_url)
token = "foobarbaz"
VagrantPlugins::LoginCommand::Client.new(iso_env).store_token(token)
original = [
"http://google.com/box.box",
"http://app.vagrantup.com/foo.box",
"http://vagrantcloud.com/foo.box",
"http://vagrantcloud.com/bar.box?arg=true",
"http://example.com/bar.box"
]
expected = original.dup
expected[1] = "#{original[1]}?access_token=#{token}"
expected[2] = "#{original[2]}?access_token=#{token}"
expected[3] = "#{original[3]}&access_token=#{token}"
expected.last.replace(expected.last + "?access_token=#{token}")
expect(subject).to receive(:sleep).once
expect(ui).to receive(:warn).once
env[:box_urls] = original.dup
subject.call(env)
@ -87,6 +112,17 @@ describe VagrantPlugins::LoginCommand::AddAuthentication do
expect(env[:box_urls]).to eq(expected)
end
it "modifies host URL to target if authorized host" do
originals = VagrantPlugins::LoginCommand::AddAuthentication::
REPLACEMENT_HOSTS.map{ |h| "http://#{h}/box.box" }
expected = "http://#{VagrantPlugins::LoginCommand::AddAuthentication::TARGET_HOST}/box.box"
env[:box_urls] = originals
subject.call(env)
env[:box_urls].each do |url|
expect(url).to eq(expected)
end
end
it "does not append multiple access_tokens" do
token = "foobarbaz"
VagrantPlugins::LoginCommand::Client.new(iso_env).store_token(token)