vagrant-gsauth 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 53c5257aa38fa117c1ceefa223db18ba419dece1
4
+ data.tar.gz: dfffba687e143e9326e2c5349101ce9e7dfdeddc
5
+ SHA512:
6
+ metadata.gz: 0c918eafc59052be0732051acfa8d3387f06249ce4fddd8914b58e0bb673fc094016ca3403e9eff87f57afcb25e911c94f2e6155b97edf643f65e60aa543ff79
7
+ data.tar.gz: accff56a518fb2db6a68fde1ea27c3a978ce7381aeeab5198e7a93db6c9144319b2afaf8ee531f32fd54cad7b1b7058167fe5bf118f7de4bd8130cb6e2a09ed8
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+
3
+ pkg
4
+ *.gem
5
+ .env
6
+ Gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,33 @@
1
+ Lint/AssignmentInCondition:
2
+ Enabled: false
3
+
4
+ Metrics/AbcSize:
5
+ Max: 40
6
+
7
+ Metrics/CyclomaticComplexity:
8
+ Max: 12
9
+
10
+ Metrics/LineLength:
11
+ Max: 100
12
+
13
+ Metrics/MethodLength:
14
+ CountComments: false
15
+ Max: 25
16
+
17
+ Metrics/PerceivedComplexity:
18
+ Max: 15
19
+
20
+ Style/AlignParameters:
21
+ EnforcedStyle: with_fixed_indentation
22
+
23
+ Style/Documentation:
24
+ Enabled: false
25
+
26
+ Style/FileName:
27
+ Enabled: false
28
+
29
+ Style/RescueModifier:
30
+ Enabled: false
31
+
32
+ Style/SignalException:
33
+ EnforcedStyle: only_raise
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.3
data/.travis.yml ADDED
@@ -0,0 +1,51 @@
1
+ sudo: false
2
+
3
+ language: ruby
4
+ rvm:
5
+ - 2.2.3
6
+
7
+ addons:
8
+ apt:
9
+ packages:
10
+ - bsdtar
11
+ - libxslt1.1
12
+
13
+ before_install:
14
+ # Install Bats, the Bash testing framework
15
+ - npm install bats
16
+
17
+ # Speed up Nokogiri installation substantially by using precompiled libxslt
18
+ - bundle config build.nokogiri --use-system-libraries
19
+
20
+ # Older versions of Vagrant can't handle the current version of Bundler, which
21
+ # ships with Travis.
22
+ - rvm @default,@global do gem uninstall bundler --all --executables
23
+ - gem install bundler -v '~> 1.5.2'
24
+ - bundle --version
25
+
26
+ before_script:
27
+ - test/setup.rb
28
+
29
+ after_script:
30
+ - test/cleanup.rb
31
+
32
+ env:
33
+ global:
34
+ - VAGRANT_S3AUTH_ATLAS_BOX_NAME="travis-$TRAVIS_JOB_NUMBER"
35
+ - VAGRANT_S3AUTH_BUCKET="travis-$TRAVIS_JOB_NUMBER.vagrant-gsauth.com"
36
+ - VAGRANT_S3AUTH_REGION_NONSTANDARD=eu-west-1
37
+ - VAGRANT_S3AUTH_BOX_BASE=minimal
38
+ matrix:
39
+ - VAGRANT_VERSION=master
40
+ - VAGRANT_VERSION=v1.8.1
41
+ - VAGRANT_VERSION=v1.7.4
42
+ - VAGRANT_VERSION=v1.6.5
43
+ - VAGRANT_VERSION=v1.5.1
44
+
45
+ deploy:
46
+ provider: rubygems
47
+ api_key:
48
+ secure: foobar
49
+ on:
50
+ tags: true
51
+ repo: ConduceInc/vagrant-gsauth
@@ -0,0 +1 @@
1
+ 1.5:e21ed4ad-df79-4ce2-92e7-737f03004c9a
@@ -0,0 +1 @@
1
+ 1480608574
@@ -0,0 +1 @@
1
+ e21ed4ad-df79-4ce2-92e7-737f03004c9a
@@ -0,0 +1 @@
1
+ b8501bb300114a7fb421a3e4ddc35121
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEowIBAAKCAQEA1ZRGw9t6XM5AAMPcRFHYyJkhSLSXhD0Y3VThjVCiazc23xvO
3
+ FQL/wd7Cz7UkjwplHOP2CN2FPFHJqLHVhn5PtCYIZLOHAHL4WzhYqm2sIVyLBbWI
4
+ lsHHgH25wRXrR50za437QtqPIb/brs5auNKOi4Q0elIeCah9G8tKBf/jbDB1ibXY
5
+ L3XVALvBIb6U0dtf0mURgdaT+Ql35UzH5hqQDuT+uB0sfKgKozl9LnxGN0MG45L/
6
+ jqmOBfffLAnHGe7EOTQFIli9hgIbliwgZfTpCY4wQrOyceCvzU/R11QH/+zbsUQe
7
+ hAoRjWob0uENeI7qOYs4ea2t/A/BfWjgJJtk1wIDAQABAoIBAA4dRWvuFjEJ5Ero
8
+ pqbRLd1b2Uo/vP+dNgZydJFtMb6aIIMwCDd1QkeinAcz9l2Jl1MIcZr2YLayxPvj
9
+ /LNtp4DFPqrA/nv2HRmSKLHim4x83CcdbxBfb/q61ErBUxIhfmNuN5uca/cUAcWU
10
+ l4Q9TfREYV9wC9Ihk1sB3Tt2RKZCkqn2DJ8zmeOktNQEU4CvHjRu7/SD58scE3Db
11
+ gEZfaUDKPdzhDvnHtSiP1g+NJRYvY5zPZLcjwA8XEJw0qrIwpK7hDYJ0iTtqPWRR
12
+ z+54sy9rp85BzRbM+UpRiP0RRDrFrP6Suz+vAm7wXE5ivwHEMfAAfeqE4fk2emIU
13
+ Et1+GkECgYEA6ya2bsj8X1yiMdxfwjaKrPpEm3zaxiRHavKS8H9I7fiPs88dbEL1
14
+ uP0P/SMFzb1ipoLZ1goQLsLs1XIrdZhNwEpG3nPUBUkz5hiGipa2gKG2Nt108L6P
15
+ Dawd1t/vhzU2JVIjG6EKKNoWBx2UEOc6/LYXsw6crxpT1cVzXTDkACECgYEA6IPw
16
+ L7IAk6df7igpW4+iVZjfPbifk31nKvq1hMZqkdIIh+c6/Iadom9PO96WSuI8AcrD
17
+ l+bPceP9Kkdq4oIzMuTVmlPXyTRiWM4FzKVMYLbhp5gaFrjuNP9lNaAxLdwoCaQg
18
+ BFcDzaG56Sj5NM8VpQjVlmG9NZxfcIDIl5tKpfcCgYB4L5kelmsm8lmT0ma/BNFs
19
+ B535Op82lmRKLSEc+nFz747DACCxrKeanP0HDFdzCFDbehWMaChNPiN+FJRRzj4v
20
+ Acem+txqtzdnazGYs98jb4OKFzYltb+35Th7EomCOZgrCwgWnwBqUMzhZiS/Xu+v
21
+ KgKC6fz7IiGnKPwFrW9bAQKBgGjPgKefT48/dYi/ZdU2K/D11jvWS2iKsMS4+rX9
22
+ UvCkgt/wJbDLZadhEZBlR849qNsN8Zk5m+003lv+kXnFQxr/+CF3BeBW0rZBOHAF
23
+ WyaFibaoY6o2dnpBXfgMW97WTN37s8sBBl/dNRabN6rMZm9cShtdt5LBCGyIQOPG
24
+ RqIFAoGBAMm5MPvX/rtJO8XeQVOZ0o3Rv/zpOjA/gqAhQbiMTHaPkWHBfLD0Vgmj
25
+ zehNrSp1kKaITcpf6M0XeaXX63M3tM8Vdw2vftdkR6wLMiemImNkOk7gahBieqMv
26
+ 7AU6AtLW1PdwQU6cXyRY0t4fjC5FWhdNWnLJ8Os7Qs0BajWP6PK3
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1 @@
1
+ {"virtualbox":{"/vagrant":{"guestpath":"/vagrant","hostpath":"/Users/jdipierro/Source/vagrant-s3auth","disabled":false,"__vagrantfile":true}}}
data/CHANGELOG.md ADDED
@@ -0,0 +1,135 @@
1
+ ## 1.3.0
2
+
3
+ **18 January 2016**
4
+
5
+ Enhancements:
6
+
7
+ * upgrade to AWS SDK v2.2.10
8
+
9
+ Fixes:
10
+
11
+ * allow box update checks when offline ([#26])
12
+ * support the Vagrant 1.8.x series ([#27])
13
+
14
+ ## 1.2.0
15
+
16
+ **20 August 2015**
17
+
18
+ Enhancements:
19
+
20
+ * output the discovered AWS access key and its source (environment variable or
21
+ profile) when downloading an authenticated S3 box ([#21])
22
+
23
+ Thanks, [@Daemoen][Daemoen]!
24
+
25
+ ## 1.1.1
26
+
27
+ **6 August 2015**
28
+
29
+ Enhancements:
30
+
31
+ * bump dependencies to latest patch versions and dev dependencies to latest
32
+ versions
33
+
34
+ ## 1.1.0
35
+
36
+ **1 June 2015**
37
+
38
+ Enhancements:
39
+
40
+ * upgrade to AWS SDK v2 ([#15])
41
+ * recommend the use of the AWS SDK's centralized credential file ([#14])
42
+
43
+ Fixes:
44
+
45
+ * allow up to ten minutes of time skew ([#16])
46
+ * try an unauthenticated download before demanding AWS credentials ([#10])
47
+
48
+ Thanks, [@kimpepper][kimpepper] and [@companykitchen-dev][companykitchen-dev]!
49
+
50
+ ## 1.0.3
51
+
52
+ **10 March 2015**
53
+
54
+ Fixes:
55
+
56
+ * fix namespace collisions with [vagrant-aws][vagrant-aws] ([#11])
57
+
58
+ Thanks, [@andres-rojas][andres-rojas]!
59
+
60
+
61
+ ## 1.0.2
62
+
63
+ **25 December 2014**
64
+
65
+ Enhancements:
66
+
67
+ * provide better error messages when S3 API requests are denied ([#9])
68
+ * include IAM policy recommendations in README
69
+
70
+ ## 1.0.1
71
+
72
+ **21 December 2014**
73
+
74
+ Enhancements:
75
+
76
+ * support bucket-in-host style S3 URLs to simplify usage instructions
77
+
78
+ Fixes:
79
+
80
+ * internal cleanup
81
+ * improved detection of incompatible Vagrant versions
82
+
83
+ ## 1.0.0
84
+
85
+ **16 December 2014**
86
+
87
+ Enhancements:
88
+
89
+ * passes a complete acceptance test suite
90
+ * detects full and shorthand S3 URLs at all download stages
91
+
92
+ Fixes:
93
+
94
+ * automatically determines region for shorthand S3 URLs ([#1], [#7])
95
+
96
+ ## 0.1.0
97
+
98
+ **13 June 2014**
99
+
100
+ Enhancements:
101
+
102
+ * support buckets hosted in any S3 region ([#1])
103
+
104
+ Fixes:
105
+
106
+ * properly authenticate requests for simple (non-metadata) S3 boxes ([#1])
107
+
108
+ ## 0.0.2
109
+
110
+ **6 June 2014**
111
+
112
+ Enhancements:
113
+
114
+ * formally license under MIT
115
+
116
+ ## 0.0.1
117
+
118
+ * initial release
119
+
120
+ [#1]: https://github.com/WhoopInc/vagrant-s3auth/issues/1
121
+ [#7]: https://github.com/WhoopInc/vagrant-s3auth/issues/7
122
+ [#9]: https://github.com/WhoopInc/vagrant-s3auth/issues/9
123
+ [#10]: https://github.com/WhoopInc/vagrant-s3auth/issues/10
124
+ [#11]: https://github.com/WhoopInc/vagrant-s3auth/pull/11
125
+ [#14]: https://github.com/WhoopInc/vagrant-s3auth/issues/14
126
+ [#15]: https://github.com/WhoopInc/vagrant-s3auth/issues/15
127
+ [#16]: https://github.com/WhoopInc/vagrant-s3auth/issues/16
128
+ [#21]: https://github.com/WhoopInc/vagrant-s3auth/issues/21
129
+
130
+ [Daemoen]: https://github.com/Daemoen
131
+ [andres-rojas]: https://github.com/andres-rojas
132
+ [companykitchen-dev]: https://github.com/companykitchen-dev
133
+ [kimpepper]: https://github.com/kimpepper
134
+
135
+ [vagrant-aws]: https://github.com/mitchellh/vagrant-aws
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,40 @@
1
+ # Contributing
2
+
3
+ We love contributions! Pull request away.
4
+
5
+ ## Hacking
6
+
7
+ You'll need Ruby and Bundler, of course. Then, check out the code and install
8
+ the gems:
9
+
10
+ ```bash
11
+ $ git clone git@github.com:conduceinc/vagrant-gsauth.git
12
+ $ cd vagrant-gsauth
13
+ $ bundle
14
+ ```
15
+
16
+ Hack away! When you're ready to test, either [run the test suite](TESTING.md) or
17
+ run Vagrant manually *using the configured Bundler environment*:
18
+
19
+ ```bash
20
+ $ VAGRANT_LOG=debug bundle exec vagrant box add S3_URL
21
+ ```
22
+
23
+ If you forget the `bundle exec`, you'll use system Vagrant—not the Vagrant that
24
+ has your plugin changes installed!
25
+
26
+ ## Guidelines
27
+
28
+ We do ask that all contributions pass the linter and test suite. Travis will
29
+ automatically run these against your contribution once you submit the pull
30
+ request, but you can also run them locally as you go!
31
+
32
+ ### Linting
33
+
34
+ ```bash
35
+ $ rake lint
36
+ ```
37
+
38
+ ### Testing
39
+
40
+ See [TESTING](TESTING.md).
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ VAGRANT_REF = ENV['VAGRANT_VERSION'] || 'master'
4
+
5
+ group :development do
6
+ gem 'vagrant', git: 'git://github.com/mitchellh/vagrant.git', ref: VAGRANT_REF
7
+ end
8
+
9
+ group :plugins do
10
+ gemspec
11
+ gem 'google-api-client', require: 'google/apis/storage_v1'
12
+ gem 'vagrant-aws', git: 'git://github.com/mitchellh/vagrant-aws.git', ref: 'master'
13
+ end
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2014 WHOOP, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # vagrant-gsauth
2
+
3
+ <a href="https://travis-ci.org/ConduceInc/vagrant-gsauth">
4
+ <img src="https://travis-ci.org/ConduceInc/vagrant-gsauth.svg?branch=master"
5
+ align="right">
6
+ </a>
7
+
8
+ Private, versioned Vagrant boxes hosted in Google Cloud Storage.
9
+
10
+ ## Installation
11
+
12
+ From the command line:
13
+
14
+ ```bash
15
+ $ vagrant plugin install vagrant-gsauth
16
+ ```
17
+
18
+ ### Requirements
19
+
20
+ * [Vagrant][vagrant], v1.5.1+
21
+
22
+ ## Usage
23
+
24
+ vagrant-gsauth will parse GS URLs:
25
+
26
+ ```
27
+ gs://bucket/path/to/metadata
28
+ ```
29
+
30
+ And authorize the request using your Google Cloud SDK login.
31
+
32
+ This means you can host your team's sensitive, private boxes in Google Storage, and use your
33
+ developers' existing Google credentials to securely grant access.
34
+
35
+ If you've already got your credentials stored in the standard environment
36
+ variables:
37
+
38
+ ```ruby
39
+ # Vagrantfile
40
+
41
+ Vagrant.configure('2') do |config|
42
+ config.vm.box = 'simple-secrets'
43
+ config.vm.box_url = 'gs://example.com/secret.box'
44
+ end
45
+ ```
46
+
47
+ ### Configuration
48
+
49
+ #### Google Cloud credentials
50
+
51
+ https://cloud.google.com/sdk/
52
+
53
+ #### GS URLs
54
+
55
+ You can use the gs protocol shorthand
56
+
57
+ ```
58
+ gs://bucket/resource
59
+ ```
60
+
61
+ which expands to full path HTTPS URL.
62
+
63
+ #### Simple boxes
64
+
65
+ Simply point your `box_url` at a google storage URL:
66
+
67
+ ```ruby
68
+ Vagrant.configure('2') do |config|
69
+ config.vm.box = 'simple-secrets'
70
+ config.vm.box_url = 'gs://bucket/secret.box'
71
+ end
72
+ ```
73
+
74
+ #### Metadata (versioned) boxes
75
+
76
+ [Metadata boxes][metadata-boxes] were added to Vagrant in 1.5 and power Vagrant
77
+ Cloud. You can host your own metadata and bypass Vagrant Cloud entirely.
78
+
79
+ Essentially, you point your `box_url` at a [JSON metadata file][metadata-boxes]
80
+ that tells Vagrant where to find all possible versions:
81
+
82
+ ```ruby
83
+ # Vagrantfile
84
+
85
+ Vagrant.configure('2') do |config|
86
+ config.vm.box = 'examplecorp/secrets'
87
+ config.vm.box_url = 'gs://bucket/secrets'
88
+ end
89
+ ```
90
+
91
+ ```json
92
+ "gs://bucket/secrets"
93
+
94
+ {
95
+ "name": "examplecorp/secrets",
96
+ "description": "This box contains company secrets.",
97
+ "versions": [{
98
+ "version": "0.1.0",
99
+ "providers": [{
100
+ "name": "virtualbox",
101
+ "url": "gs://bucket/secrets/1.0.0/secrets.box",
102
+ "checksum_type": "sha1",
103
+ "checksum": "foo"
104
+ }]
105
+ }]
106
+ }
107
+ ```
108
+
109
+ **IMPORTANT:** Your metadata *must* be served with `Content-Type: application/json`
110
+ or Vagrant will not recognize it as metadata!
111
+
112
+ ## Auto-install
113
+
114
+ The beauty of Vagrant is the magic of "`vagrant up` and done." Making your users
115
+ install a plugin is lame.
116
+
117
+ But wait! Just stick some shell in your Vagrantfile:
118
+
119
+ ```ruby
120
+ unless Vagrant.has_plugin?('vagrant-gsauth')
121
+ # Attempt to install ourself. Bail out on failure so we don't get stuck in an
122
+ # infinite loop.
123
+ system('vagrant plugin install vagrant-gsauth') || exit!
124
+
125
+ # Relaunch Vagrant so the plugin is detected. Exit with the same status code.
126
+ exit system('vagrant', *ARGV)
127
+ end
128
+ ```
129
+
130
+ [metadata-boxes]: http://docs.vagrantup.com/v2/boxes/format.html
131
+ [vagrant]: http://vagrantup.com
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rubocop/rake_task'
4
+
5
+ Dir.chdir(File.expand_path('../', __FILE__))
6
+
7
+ Bundler::GemHelper.install_tasks
8
+
9
+ RuboCop::RakeTask.new(:lint)
10
+
11
+ task :test do
12
+ sh 'bats test/run.bats'
13
+ end
14
+
15
+ task default: %w(lint test)
data/TESTING.md ADDED
@@ -0,0 +1,51 @@
1
+ # Testing
2
+
3
+ No unit testing, since the project is so small. But a full suite of acceptance
4
+ tests that run using [Bats: Bash Automated Testing System][bats]! Basically, the
5
+ acceptance tests run `vagrant box add GS_URL` with a bunch of GS URLs and box
6
+ types, and assert that everything works!
7
+
8
+ See [the .travis.yml CI configuration](.travis.yml) for a working example.
9
+
10
+ ## Environment variables
11
+
12
+ You'll need to export the below. Recommended values included when not sensitive.
13
+
14
+ ```bash
15
+ # Base name of bucket. Must be unique.
16
+ export VAGRANT_GSAUTH_BUCKET="vagrant-gsauth"
17
+ # The test box to use. Currently only 1.
18
+ export VAGRANT_GSAUTH_BOX_BASE="minimal"
19
+ # The Google Cloud project that the tests will create buckets and objects under.
20
+ export VAGRANT_GSAUTH_PROJECT="someproject-1234567"
21
+ ```
22
+
23
+ [bats]: https://github.com/sstephenson/bats
24
+
25
+ ## Running tests
26
+
27
+ You'll need [Bats][bats] installed! Then:
28
+
29
+ ```bash
30
+ # export env vars as described
31
+ $ test/setup.rb
32
+ $ rake test
33
+ # hack hack hack
34
+ $ rake test
35
+ $ test/cleanup.rb
36
+ ```
37
+
38
+ ## Scripts
39
+
40
+ ### test/setup.rb
41
+
42
+ Creates a Google Cloud Storage bucket with the contents of the box
43
+ directory.
44
+
45
+ ### test/cleanup.rb
46
+
47
+ Destroys GS buckets and objects.
48
+
49
+ ## run.bats
50
+
51
+ Attempts to `vagrant box add` the boxes from Google Storage.
@@ -0,0 +1,14 @@
1
+ require 'pathname'
2
+
3
+ require 'vagrant-gsauth/plugin'
4
+
5
+ module VagrantPlugins
6
+ module GSAuth
7
+ def self.source_root
8
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
9
+ end
10
+
11
+ I18n.load_path << File.expand_path('locales/en.yml', source_root)
12
+ I18n.reload!
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ require 'vagrant'
2
+
3
+ module VagrantPlugins
4
+ module GSAuth
5
+ module Errors
6
+ class VagrantGSAuthError < Vagrant::Errors::VagrantError
7
+ error_namespace('vagrant_s3auth.errors')
8
+ end
9
+
10
+ class UnknownBucketError < VagrantGSAuthError
11
+ error_key(:unknown_bucket)
12
+ end
13
+
14
+ class MalformedShorthandURLError < VagrantGSAuthError
15
+ error_key(:malformed_shorthand_url)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,60 @@
1
+ require 'uri'
2
+
3
+ require 'vagrant/util/downloader'
4
+ require 'vagrant-gsauth/util'
5
+ require 'google/apis/errors'
6
+
7
+ GSAuth = VagrantPlugins::GSAuth
8
+
9
+ module Vagrant
10
+ module Util
11
+ class Downloader
12
+ def gsauth_download(options, subprocess_options, &data_proc)
13
+ # The URL sent to curl is always the last argument. We have to rely
14
+ # on this implementation detail because we need to hook into both
15
+ # HEAD and GET requests.
16
+ url = options.last
17
+ gs_object = GSAuth::Util.get_object(url)
18
+ return unless gs_object
19
+
20
+ @logger.info("gsauth: Discovered GS URL: #{@source}")
21
+ @logger.debug("gsauth: Bucket: #{gs_object.bucket}")
22
+ @logger.debug("gsauth: Object: #{gs_object.name}")
23
+
24
+ url.replace(gs_object.media_link)
25
+ @logger.debug("gsauth: Media download link: #{gs_object.media_link}")
26
+
27
+ auth_headers = GSAuth::Util.authorization_header
28
+
29
+ options.insert(0, *auth_headers.map { |k, v| ['-H', "#{k}: #{v}"] }.flatten)
30
+
31
+ execute_curl_without_gsauth(options, subprocess_options, &data_proc)
32
+ rescue Errors::DownloaderError => e
33
+ if e.message =~ /403 Forbidden/
34
+ e.message << "\n\n"
35
+ e.message << I18n.t('vagrant_gsauth.errors.box_download_forbidden',
36
+ bucket: gs_object && gs_object.bucket.name)
37
+ end
38
+ raise
39
+ rescue Google::Apis::Error => e
40
+ raise Errors::DownloaderError, message: e
41
+ rescue ::Seahorse::Client::NetworkingError => e
42
+ # Vagrant ignores download errors during e.g. box update checks
43
+ # because an internet connection isn't necessary if the box is
44
+ # already downloaded. Vagrant isn't expecting AWS's
45
+ # Seahorse::Client::NetworkingError, so we cast it to the
46
+ # DownloaderError Vagrant expects.
47
+ raise Errors::DownloaderError, message: e
48
+ end
49
+
50
+ def execute_curl_with_gsauth(options, subprocess_options, &data_proc)
51
+ @ui.clear_line if @ui
52
+
53
+ gsauth_download(options, subprocess_options, &data_proc) || (raise e)
54
+ end
55
+
56
+ alias execute_curl_without_gsauth execute_curl
57
+ alias execute_curl execute_curl_with_gsauth
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ require 'uri'
2
+
3
+ module VagrantPlugins
4
+ module GSAuth
5
+ class ExpandGSUrls
6
+ def initialize(app, _)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ env[:box_urls].map! do |url_string|
12
+ url = URI(url_string)
13
+
14
+ if url.scheme == 'gs'
15
+ bucket = url.host
16
+ key = url.path[1..-1]
17
+ raise Errors::MalformedShorthandURLError, url: url unless bucket && key
18
+ next "https://storage.cloud.google.com/#{bucket}/#{key}"
19
+ end
20
+
21
+ url_string
22
+ end
23
+
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Vagrant S3Auth plugin must be run within Vagrant.'
5
+ end
6
+
7
+ require_relative 'errors'
8
+ require_relative 'extension/downloader'
9
+
10
+ module VagrantPlugins
11
+ module GSAuth
12
+ class Plugin < Vagrant.plugin('2')
13
+ Vagrant.require_version('>= 1.5.1')
14
+
15
+ name 'gsauth'
16
+
17
+ description <<-DESC
18
+ Use versioned Vagrant boxes with Google Cloud authentication.
19
+ DESC
20
+
21
+ action_hook(:gs_urls, :authenticate_box_url) do |hook|
22
+ require_relative 'middleware/expand_gs_urls'
23
+ hook.prepend(ExpandGSUrls)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,49 @@
1
+ require 'log4r'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+ require 'googleauth'
6
+ require 'google/apis/storage_v1'
7
+
8
+ module VagrantPlugins
9
+ module GSAuth
10
+ module Util
11
+ MEDIA_URL_MATCHER = %r{
12
+ ^\/download\/storage\/v1\/b\/ # Literal string '/download/storage/v1/b/'
13
+ (?<bucket>[[:alnum:]_\-]+) # Sequence of alphnumeric characters plus _ and -
14
+ \/o\/ # Literal string '/o/'
15
+ (?<key>[[:alnum:]\-_]+) # Next sequence of alphnumeric characters plus _ and -
16
+ }x
17
+
18
+ def self.storage_svc
19
+ svc = Google::Apis::StorageV1::StorageService.new
20
+ scopes = ['https://www.googleapis.com/auth/devstorage.read_only']
21
+ svc.authorization = Google::Auth.get_application_default(scopes)
22
+ svc
23
+ end
24
+
25
+ def self.get_object(url)
26
+ url = URI(url)
27
+
28
+ if url.scheme == 'gs'
29
+ bucket = url.host
30
+ key = url.path.split('/').last
31
+ elsif match = MEDIA_URL_MATCHER.match(url.path)
32
+ bucket = match['bucket']
33
+ key = match['key']
34
+ else
35
+ components = url.path.split('/').delete_if(&:empty?)
36
+ bucket = components.shift
37
+ key = components.join('/')
38
+ end
39
+
40
+ storage_svc.get_object(bucket, key) if bucket && key
41
+ end
42
+
43
+ def self.authorization_header
44
+ auth_headers = {}
45
+ storage_svc.authorization.apply(auth_headers)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module GSAuth
3
+ VERSION = '1.0.0'.freeze
4
+ end
5
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,56 @@
1
+ en:
2
+ vagrant_s3auth:
3
+ downloader:
4
+ env_credential_provider: |-
5
+ Signing S3 request with key '%{access_key}' loaded from $%{env_var}
6
+
7
+ profile_credential_provider: |-
8
+ Signing S3 request with key '%{access_key}' loaded from profile '%{profile}'
9
+
10
+ errors:
11
+ missing_credentials: |-
12
+ Unable to find AWS credentials.
13
+
14
+ Ensure the following variables are set in your environment, or set
15
+ them at the top of your Vagrantfile:
16
+
17
+ AWS_ACCESS_KEY_ID
18
+ AWS_SECRET_ACCESS_KEY
19
+
20
+ Alternatively, you can create a credential profile and set the
21
+
22
+ AWS_PROFILE
23
+
24
+ environment variable. Consult the documentation for details.
25
+
26
+ malformed_shorthand_url: |-
27
+ Malformed shorthand GS box URL:
28
+
29
+ %{url}
30
+
31
+ Check your `box_url` setting.
32
+
33
+ s3_api_error: |-
34
+ Unable to communicate with Amazon S3 to download box. The S3 API reports:
35
+
36
+ %{error}
37
+
38
+ bucket_location_access_denied_error: |-
39
+ Request for box's Amazon S3 region was denied.
40
+
41
+ This usually indicates that your user account is misconfigured. Ensure
42
+ your IAM policy allows the "s3:GetBucketLocation" action for your bucket:
43
+
44
+ arn:aws:s3:::%{bucket}
45
+
46
+ box_download_forbidden: |-
47
+ This box is hosted on Amazon S3. A 403 Forbidden error usually indicates
48
+ that your user account is misconfigured. Ensure your IAM policy allows
49
+ the "s3:GetObject" action for your bucket:
50
+
51
+ arn:aws:s3:::%{bucket}/*
52
+
53
+ It may also indicate the box does not exist, so check your spelling.
54
+
55
+ unknown_bucket: |-
56
+ Unable to determine the bucket
data/test/box/minimal ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "%{bucket}/minimal",
3
+ "description": "This box contains company secrets.",
4
+ "versions": [{
5
+ "version": "1.0.1",
6
+ "providers": [{
7
+ "name": "virtualbox",
8
+ "url": "%{box_url}",
9
+ "checksum_type": "sha1",
10
+ "checksum": "8ea536dd3092cf159f02405edd44ded5b62ba4e6"
11
+ }]
12
+ }]
13
+ }
Binary file
data/test/cleanup.rb ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'googleauth'
5
+ require 'google/apis/storage_v1'
6
+
7
+ require_relative 'support'
8
+
9
+ svc = Google::Apis::StorageV1::StorageService.new
10
+ svc.authorization = Google::Auth.get_application_default(SCOPES)
11
+
12
+ svc.delete_object(BUCKET, BOX_BASE)
13
+ svc.delete_object(BUCKET, "#{BOX_BASE}.box")
14
+ sleep 1
15
+ svc.delete_bucket(BUCKET)
data/test/run.bats ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bats
2
+
3
+ missing_vars=()
4
+
5
+ require_var() {
6
+ [[ "${!1}" ]] || missing_vars+=("$1")
7
+ }
8
+
9
+ require_var VAGRANT_GSAUTH_BUCKET
10
+ require_var VAGRANT_GSAUTH_BOX_BASE
11
+ require_var VAGRANT_GSAUTH_PROJECT
12
+
13
+ if [[ ${#missing_vars[*]} -gt 0 ]]; then
14
+ echo "Missing required environment variables:"
15
+ printf ' %s\n' "${missing_vars[@]}"
16
+ exit 1
17
+ fi
18
+
19
+ teardown() {
20
+ bundle exec vagrant box remove "$VAGRANT_GSAUTH_BUCKET/$VAGRANT_GSAUTH_BOX_BASE" > /dev/null 2>&1 || true
21
+ }
22
+
23
+ @test "simple box with shorthand url" {
24
+ bundle exec vagrant box add --name "$VAGRANT_GSAUTH_BUCKET/$VAGRANT_GSAUTH_BOX_BASE" "gs://$VAGRANT_GSAUTH_BUCKET/$VAGRANT_GSAUTH_BOX_BASE.box"
25
+ }
26
+
27
+ @test "metadata box with shorthand url" {
28
+ bundle exec vagrant box add "gs://$VAGRANT_GSAUTH_BUCKET/$VAGRANT_GSAUTH_BOX_BASE"
29
+ }
30
+
31
+ @test "garbage shorthand url" {
32
+ run bundle exec vagrant box add --name "$VAGRANT_GSAUTH_BUCKET/$VAGRANT_GSAUTH_BOX_BASE" gs://wubbalubbadubdub
33
+ [[ "$status" -eq 1 ]]
34
+ [[ "$output" == *"Malformed shorthand GS box URL"* ]]
35
+ }
data/test/setup.rb ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'googleauth'
5
+ require 'google/apis/storage_v1'
6
+
7
+ require_relative 'support'
8
+
9
+ ROOT = Pathname.new(File.dirname(__FILE__))
10
+
11
+ svc = Google::Apis::StorageV1::StorageService.new
12
+ svc.authorization = Google::Auth.get_application_default(SCOPES)
13
+ svc.insert_bucket(PROJECT, Google::Apis::StorageV1::Bucket.new(name: BUCKET))
14
+
15
+ box_file = File.open(ROOT + Pathname.new("box/#{BOX_BASE}.box"))
16
+ box_obj = svc.insert_object(BUCKET, name: "#{BOX_BASE}.box",
17
+ upload_source: box_file,
18
+ content_type: 'application/x-gzip')
19
+
20
+ metadata_string = File.read(ROOT + Pathname.new("box/#{BOX_BASE}")) % {
21
+ bucket: BUCKET,
22
+ box_url: "https://storage.googleapis.com/#{BUCKET}/#{BOX_BASE}.box"
23
+ }
24
+
25
+ svc.insert_object(BUCKET, name: BOX_BASE,
26
+ upload_source: StringIO.new(metadata_string),
27
+ content_type: 'application/json')
28
+
29
+ box_obj.self_link
data/test/support.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'http'
2
+
3
+ PROJECT = ENV['VAGRANT_GSAUTH_PROJECT'].freeze
4
+ BUCKET = ENV['VAGRANT_GSAUTH_BUCKET'].freeze
5
+ BOX_BASE = ENV['VAGRANT_GSAUTH_BOX_BASE'].freeze
6
+ SCOPES = ['https://www.googleapis.com/auth/devstorage.read_write'].freeze
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ require 'vagrant-gsauth/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'vagrant-gsauth'
7
+ spec.version = VagrantPlugins::GSAuth::VERSION
8
+ spec.authors = ['Nikhil Benesch', 'Justin DiPierro']
9
+ spec.email = ['benesch@whoop.com', 'justin@conduce.com']
10
+ spec.summary = 'Private, versioned Vagrant boxes hosted on Google Cloud Storage.'
11
+ spec.homepage = 'https://github.com/conduceinc/vagrant-gsauth'
12
+ spec.license = 'MIT'
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.test_files = spec.files.grep(/spec/)
16
+ spec.require_paths = ['lib']
17
+
18
+ spec.add_dependency 'google-api-client', '~> 0.9'
19
+ spec.add_dependency 'googleauth', '~> 0.5.1'
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.5'
22
+ spec.add_development_dependency 'http', '~> 1.0.2'
23
+ spec.add_development_dependency 'rake', '~> 10.5.0'
24
+ spec.add_development_dependency 'rubocop', '~> 0.36.0'
25
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-gsauth
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Nikhil Benesch
8
+ - Justin DiPierro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-12-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: google-api-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.9'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.9'
28
+ - !ruby/object:Gem::Dependency
29
+ name: googleauth
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 0.5.1
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.5.1
42
+ - !ruby/object:Gem::Dependency
43
+ name: bundler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.5'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.5'
56
+ - !ruby/object:Gem::Dependency
57
+ name: http
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: 1.0.2
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.2
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: 10.5.0
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 10.5.0
84
+ - !ruby/object:Gem::Dependency
85
+ name: rubocop
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: 0.36.0
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: 0.36.0
98
+ description:
99
+ email:
100
+ - benesch@whoop.com
101
+ - justin@conduce.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rubocop.yml"
108
+ - ".ruby-version"
109
+ - ".travis.yml"
110
+ - ".vagrant/machines/default/virtualbox/action_provision"
111
+ - ".vagrant/machines/default/virtualbox/action_set_name"
112
+ - ".vagrant/machines/default/virtualbox/creator_uid"
113
+ - ".vagrant/machines/default/virtualbox/id"
114
+ - ".vagrant/machines/default/virtualbox/index_uuid"
115
+ - ".vagrant/machines/default/virtualbox/private_key"
116
+ - ".vagrant/machines/default/virtualbox/synced_folders"
117
+ - CHANGELOG.md
118
+ - CONTRIBUTING.md
119
+ - Gemfile
120
+ - LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - TESTING.md
124
+ - lib/vagrant-gsauth.rb
125
+ - lib/vagrant-gsauth/errors.rb
126
+ - lib/vagrant-gsauth/extension/downloader.rb
127
+ - lib/vagrant-gsauth/middleware/expand_gs_urls.rb
128
+ - lib/vagrant-gsauth/plugin.rb
129
+ - lib/vagrant-gsauth/util.rb
130
+ - lib/vagrant-gsauth/version.rb
131
+ - locales/en.yml
132
+ - test/box/minimal
133
+ - test/box/minimal.box
134
+ - test/cleanup.rb
135
+ - test/run.bats
136
+ - test/setup.rb
137
+ - test/support.rb
138
+ - vagrant-gsauth.gemspec
139
+ homepage: https://github.com/conduceinc/vagrant-gsauth
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.4.5.1
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Private, versioned Vagrant boxes hosted on Google Cloud Storage.
163
+ test_files:
164
+ - vagrant-gsauth.gemspec