Vagrant: Prompt for basic HTTP Auth credentials

Created on 24 Apr 2014  ยท  12Comments  ยท  Source: hashicorp/vagrant

When trying to use a box that is being behind basic http auth I get following error.

An error occurred while downloading the remote file. The error
message, if any, is reproduced below. Please fix this error and try
again.

The requested URL returned error: 401 Unauthorized

It would be very nice if vagrant could prompt for credentials.

Most helpful comment

I know this issue is closed but it's one of the first hits on google so here's my solution. Note that this is inspired by S3Auth plugin but works for basic auth by prompting for user/pass and passing http header to curl so the credentials are not visible on console. simply add this to Vagrantfile and it should work

require 'base64'
require 'vagrant/util/downloader'

#
# Extend vagrant's Downloader class to ask for basic auth credentials
module Vagrant
  module Util
    class Downloader
      @@token = ""

      def basicauth_downloader(options, subprocess_options, &data_proc)
        if @@token.empty?
          print "Username: "
          username = STDIN.gets.chomp
          print "Password: "
          password = STDIN.noecho(&:gets).chomp
          @@token = Base64.encode64("#{username}:#{password}")
        end

        options = [ "-H", "Authorization: Basic #{@@token}" ] + options
        orig_execute_curl(options, subprocess_options, &data_proc)
      end

      def execute_curl_with_basicauth(options, subprocess_options, &data_proc)
        orig_execute_curl(options, subprocess_options, &data_proc)
      rescue Errors::DownloaderError => e
        @ui.clear_line if @ui
        if e.message =~ /401 Unauthorized/
          basicauth_downloader(options, subprocess_options, &data_proc) || (raise e)
        else
          raise e
        end
      end

      alias orig_execute_curl execute_curl
      alias execute_curl execute_curl_with_basicauth
    end
  end
end

All 12 comments

It would be nice, but you can work around this by setting the user and pass in the URL. I have no plans to address this in the near future but would happily look at a PR! Thanks!

I can not add a usr/pwd in URL because it would go into git. I want to gain access to specific users only, which are managed in a separate tool.

@martinssipenko, a common way to do something like that is to use environment variables. For example:

Vagrant.configure('2') do |config|
  config.vm.box = "foo"
  config.vm.box_url = "https://#{ENV['BOX_USER']}@#{ENV['BOX_PASS']}/foo.box"
  # ...
end

@tmatilai Thanks!

This works but the password is echoed in the terminal.

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'test' could not be found. Attempting to find and install...
default: Box Provider: virtualbox
default: Box Version: >= 0
==> default: Adding box 'test' (v0) for provider: virtualbox
default: Downloading: https://user:*@files.mydomain.com/test.box
==> default: Box download was interrupted. Exiting.

Problem still exists and putting login/password in uri is not a good idea. If vagrant uses curl why don't you use it with --anyauth option to let it ask if any autenthication is needed?

Why do you leave problem without any proper solution?

We're having a similar problem too. Any chance of a revisit @mitchellh ?

I know this issue is closed but it's one of the first hits on google so here's my solution. Note that this is inspired by S3Auth plugin but works for basic auth by prompting for user/pass and passing http header to curl so the credentials are not visible on console. simply add this to Vagrantfile and it should work

require 'base64'
require 'vagrant/util/downloader'

#
# Extend vagrant's Downloader class to ask for basic auth credentials
module Vagrant
  module Util
    class Downloader
      @@token = ""

      def basicauth_downloader(options, subprocess_options, &data_proc)
        if @@token.empty?
          print "Username: "
          username = STDIN.gets.chomp
          print "Password: "
          password = STDIN.noecho(&:gets).chomp
          @@token = Base64.encode64("#{username}:#{password}")
        end

        options = [ "-H", "Authorization: Basic #{@@token}" ] + options
        orig_execute_curl(options, subprocess_options, &data_proc)
      end

      def execute_curl_with_basicauth(options, subprocess_options, &data_proc)
        orig_execute_curl(options, subprocess_options, &data_proc)
      rescue Errors::DownloaderError => e
        @ui.clear_line if @ui
        if e.message =~ /401 Unauthorized/
          basicauth_downloader(options, subprocess_options, &data_proc) || (raise e)
        else
          raise e
        end
      end

      alias orig_execute_curl execute_curl
      alias execute_curl execute_curl_with_basicauth
    end
  end
end

@mvyletel , curl cli tool itself has mode when it could recognize resource requires basic auth and promt for password itself. Is it possible to use it in your code?

And maybe you could try to write your own vagrant plugin? It could be very desired for lots of people :)

@webarchitect609 I've tried to let curl get it itself but it was not working. possibly because curl is run in subprocess. dunno...did not dig any further.

regarding the plugin I have some alpha version ready. will try to polish it a little bit before pushing it to github

@mvyletel , sounds great! Good luck! :)

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings