vagrant-s3auth 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8bd07d8c67e818f8b050629b918f2939c85d6b43
4
+ data.tar.gz: 1439d1a6f47f937886bd861affe61a38c49bee2a
5
+ SHA512:
6
+ metadata.gz: e6d3178aca6715909b44ba0e548045e3c70e752ca0ce81b8894214ac6d15ebe6612aeb85b1c35e6caffb089771b5a654c0098354ea36a31c990f3f060774c7a6
7
+ data.tar.gz: 1f79b0b7fb583e0f627ac3b6dd80bde532aab476bb80b1f42e9072a09c42842b2dd874291c81479442edd202fc46fecaf9683cddc33429020e1d0726b7509266
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .vagrant
3
+ pkg
4
+ Vagrantfile
@@ -0,0 +1,20 @@
1
+ AlignParameters:
2
+ Enabled: false
3
+
4
+ AssignmentInCondition:
5
+ Enabled: false
6
+
7
+ Documentation:
8
+ Enabled: false
9
+
10
+ LineLength:
11
+ Max: 100
12
+
13
+ MethodLength:
14
+ CountComments: false # count full line comments?
15
+ Max: 20
16
+
17
+ SignalException:
18
+ EnforcedStyle: only_raise
19
+ SupportedStyles:
20
+ - only_raise
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :plugins do
4
+ gem 'vagrant-s3auth', path: '.'
5
+ end
6
+
7
+ group :development do
8
+ gem 'vagrant', git: 'git://github.com/mitchellh/vagrant.git'
9
+ end
@@ -0,0 +1,58 @@
1
+ GIT
2
+ remote: git://github.com/mitchellh/vagrant.git
3
+ revision: b97c509c15d94ee70af8ce25739934c5dccb7452
4
+ specs:
5
+ vagrant (1.5.3.dev)
6
+ bundler (~> 1.5.2)
7
+ childprocess (~> 0.5.0)
8
+ erubis (~> 2.7.0)
9
+ i18n (~> 0.6.0)
10
+ listen (~> 2.7.1)
11
+ log4r (~> 1.1.9, < 1.1.11)
12
+ net-scp (~> 1.1.0)
13
+ net-ssh (>= 2.6.6, < 2.8.0)
14
+ rb-kqueue (~> 0.2.0)
15
+ wdm (~> 0.1.0)
16
+
17
+ PATH
18
+ remote: .
19
+ specs:
20
+ vagrant-s3auth (0.0.1)
21
+
22
+ GEM
23
+ remote: https://rubygems.org/
24
+ specs:
25
+ celluloid (0.15.2)
26
+ timers (~> 1.1.0)
27
+ celluloid-io (0.15.0)
28
+ celluloid (>= 0.15.0)
29
+ nio4r (>= 0.5.0)
30
+ childprocess (0.5.2)
31
+ ffi (~> 1.0, >= 1.0.11)
32
+ erubis (2.7.0)
33
+ ffi (1.9.3)
34
+ i18n (0.6.9)
35
+ listen (2.7.1)
36
+ celluloid (>= 0.15.2)
37
+ celluloid-io (>= 0.15.0)
38
+ rb-fsevent (>= 0.9.3)
39
+ rb-inotify (>= 0.9)
40
+ log4r (1.1.10)
41
+ net-scp (1.1.2)
42
+ net-ssh (>= 2.6.5)
43
+ net-ssh (2.7.0)
44
+ nio4r (1.0.0)
45
+ rb-fsevent (0.9.4)
46
+ rb-inotify (0.9.3)
47
+ ffi (>= 0.5.0)
48
+ rb-kqueue (0.2.2)
49
+ ffi (>= 0.5.0)
50
+ timers (1.1.0)
51
+ wdm (0.1.0)
52
+
53
+ PLATFORMS
54
+ ruby
55
+
56
+ DEPENDENCIES
57
+ vagrant!
58
+ vagrant-s3auth!
data/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ Copyright (c) 2014 WHOOP, Inc.
2
+
3
+ All right reserved.
@@ -0,0 +1,181 @@
1
+ # vagrant-s3auth
2
+
3
+ Private, versioned Vagrant boxes hosted on Amazon S3.
4
+
5
+ ## Installation
6
+
7
+ From the command line:
8
+
9
+ ```bash
10
+ $ vagrant plugin install vagrant-s3auth
11
+ ```
12
+
13
+ ### Requirements
14
+
15
+ * [Vagrant][vagrant], v1.5.0+
16
+
17
+ ## Usage
18
+
19
+ vagrant-s3auth will automatically convert S3 box URLs
20
+
21
+ ```
22
+ s3://bucket.example.com/path/to/metadata
23
+ ```
24
+
25
+ to URLs [signed with your AWS access key][aws-signed]:
26
+
27
+ ```
28
+ https://s3.amazonaws.com/bucket.example.com/path/to/metadata?AWSAccessKeyId=
29
+ AKIAIOSFODNN7EXAMPLE&Expires=1141889120&Signature=vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
30
+ ```
31
+
32
+ This means you can host your team's sensitive, private boxes on S3, and use your
33
+ developers' existing AWS credentials to securely grant access.
34
+
35
+ If you've already got your credentials stored in the appropriate 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 = 's3://example.com/secret.box'
44
+ end
45
+ ```
46
+
47
+ ### Configuration
48
+
49
+ #### AWS credentials
50
+
51
+ AWS credentials are read from the standard environment variables
52
+ `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
53
+
54
+ If you need to obtain credentials from elsewhere, drop a block like the
55
+ following at the top of your Vagrantfile:
56
+
57
+ ```ruby
58
+ creds = File.read(File.expand_path('~/.company-aws-creds')).lines
59
+ ENV['AWS_ACCESS_KEY_ID'] = creds[0]
60
+ ENV['AWS_SECRET_ACCESS_KEY'] = creds[1]
61
+ ```
62
+
63
+
64
+ #### Simple boxes
65
+
66
+ Simply point your `box_url` at Amazon S3:
67
+
68
+ ```ruby
69
+ Vagrant.configure('2') do |config|
70
+ config.vm.box = 'simple-secrets'
71
+ config.vm.box_url = 'https://s3.amazonaws.com/bucket.example.com/secret.box'
72
+ end
73
+ ```
74
+
75
+ Note that your URL must be of the form
76
+
77
+ ```
78
+ https://s3.amazonaws.com/bucket/resource
79
+ ```
80
+
81
+ Other valid forms of S3 URLs (`bucket.s3.amazonaws.com/resource.box`, etc.) will
82
+ not be detected by vagrant-s3auth.
83
+
84
+ As shorthand, `s3://` URLs will be automatically transformed. This is equivalent
85
+ to the above:
86
+
87
+ ```ruby
88
+ Vagrant.configure('2') do |config|
89
+ config.vm.box = 'simple-secrets'
90
+ config.vm.box_url = 's3://example.com/secret.box'
91
+ end
92
+ ```
93
+
94
+ **Note:** Simple box URLs must end in `.box`, or they'll be interpreted as
95
+ [metadata boxes](#metadata-boxes).
96
+
97
+ #### Vagrant Cloud
98
+
99
+ Boxes on [Vagrant Cloud][vagrant-cloud] have support for versioning, multiple
100
+ providers, and a GUI management tool. If you've got a box version on Vagrant
101
+ Cloud.
102
+
103
+ Then just configure your Vagrantfile like normal:
104
+
105
+ ```ruby
106
+ Vagrant.configure('2') do |config|
107
+ config.vm.box = 'examplecorp/secrets'
108
+ end
109
+ ```
110
+
111
+ #### Metadata boxes
112
+
113
+ [Metadata boxes][metadata-boxes] were added to Vagrant in 1.5 and power Vagrant
114
+ Cloud. You can host your own metadata and bypass Vagrant Cloud entirely.
115
+
116
+ Essentially, you point your `box_url` at a [JSON metadata file][metadata-boxes]
117
+ that tells Vagrant where to find all possible versions:
118
+
119
+ ```ruby
120
+ # Vagrantfile
121
+
122
+ Vagrant.configure('2') do |config|
123
+ config.vm.box = 'examplecorp/secrets'
124
+ config.vm.box_url = 's3://example.com/secrets'
125
+ end
126
+ ```
127
+
128
+ ```json
129
+ "s3://example.com/secrets"
130
+
131
+ {
132
+ "name": "examplecorp/secrets",
133
+ "description": "This box contains company secrets.",
134
+ "versions": [{
135
+ "version": "0.1.0",
136
+ "providers": [{
137
+ "name": "virtualbox",
138
+ "url": "https://s3.amazonaws.com/example.com/secrets.box",
139
+ "checksum_type": "sha1",
140
+ "checksum": "foo"
141
+ }]
142
+ }]
143
+ }
144
+ ```
145
+
146
+ **Note:** box URLs in metadata JSON must use the
147
+ `s3.amazonaws.com/bucket.example.com/resource.box` URL form, or it won't get
148
+ auto-signed.
149
+
150
+ ### Rules
151
+
152
+ To sum up:
153
+
154
+ * Only the `box_url` setting can use the `s3://` shorthand. URLs entered on the
155
+ Vagrant Cloud management interface and in JSON metadata must use the full
156
+ HTTPS URL.
157
+
158
+ * The full HTTPS URL must be of the form
159
+ `https://s3.amazonaws.com/bucket.example.com/resource.box`, or it won't be
160
+ signed properly.
161
+
162
+ * Metadata box files must *not* end in `.box`.
163
+
164
+ * Actual box files *must* end in `.box`.
165
+
166
+ ### Auto-install
167
+
168
+ The beauty of Vagrant is the magic of "`vagrant up` and done." Making your users
169
+ install a plugin is lame.
170
+
171
+ But wait! Just stick some shell in your Vagrantfile:
172
+
173
+ ```ruby
174
+ %x(vagrant plugin install vagrant-s3auth) unless Vagrant.has_plugin?('vagrant-s3auth')
175
+ ```
176
+
177
+
178
+ [aws-signed]: http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth
179
+ [metadata-boxes]: http://docs.vagrantup.com/v2/boxes/format.html
180
+ [vagrant]: http://vagrantup.com
181
+ [vagrant-cloud]: http://vagrantcloud.com
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ Dir.chdir(File.expand_path('../', __FILE__))
5
+
6
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,14 @@
1
+ require 'pathname'
2
+
3
+ require 'vagrant-s3auth/plugin'
4
+
5
+ module VagrantPlugins
6
+ module S3Auth
7
+ S3_HOST = 's3.amazonaws.com'
8
+ BOX_URL_MATCHER = %r{^s3://(?<bucket>[[:alnum:]\-\.]+)(?<resource>.*)/?}
9
+
10
+ def self.source_root
11
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'action/authenticate_box_url'
2
+ require_relative 'action/box_add'
3
+
4
+ module VagrantPlugins
5
+ module S3Auth
6
+ module Action
7
+ def self.authenticate_box_url
8
+ Vagrant::Action::Builder.new.tap do |b|
9
+ b.use AuthenticateBoxUrl
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,86 @@
1
+ require 'base64'
2
+ require 'cgi'
3
+ require 'log4r'
4
+ require 'openssl'
5
+ require 'uri'
6
+
7
+ module VagrantPlugins
8
+ module S3Auth
9
+ module Action
10
+ class AuthenticateBoxUrl
11
+ def initialize(app, env)
12
+ @app = app
13
+ @logger = Log4r::Logger.new('vagrant_s3auth::action::authenticate_box_url')
14
+ @access_key = ENV['AWS_ACCESS_KEY_ID']
15
+ @secret_key = ENV['AWS_SECRET_ACCESS_KEY']
16
+ end
17
+
18
+ def call(env)
19
+ env[:box_urls].map! do |url_string|
20
+ begin
21
+ url = URI.parse(url_string)
22
+ rescue URI::InvalidURIError
23
+ next url_string
24
+ end
25
+
26
+ unless s3_url?(url)
27
+ @logger.debug("Skipping non-S3 host: #{url}")
28
+ next url_string
29
+ end
30
+
31
+ # Vagrant makes a HEAD request for metadata. S3 doesn't support
32
+ # query-string authentication on HEAD requests, so skip signing. We
33
+ # need to provide a different "authenticated" URL, though, or
34
+ # Vagrant will think the box doesn't require authentication,
35
+ # and won't request an authenticated URL for the box itself.
36
+ unless box_url?(url)
37
+ @logger.debug("Munging S3 metadata URL: #{url}")
38
+ next url_string + '?'
39
+ end
40
+
41
+ @logger.info("Signing URL for S3 box: #{url}")
42
+ sign(url)
43
+ end
44
+
45
+ @app.call(env)
46
+ end
47
+
48
+ def sign(url)
49
+ ensure_credentials
50
+
51
+ expires = (Time.now + 20).to_i
52
+ message = "GET\n\n\n#{expires}\n#{url.path}"
53
+ signature = CGI.escape(Base64.strict_encode64(
54
+ OpenSSL::HMAC.digest('sha1', @secret_key, message)))
55
+
56
+ url.query = {
57
+ 'AWSAccessKeyId' => @access_key,
58
+ 'Expires' => expires,
59
+ 'Signature' => signature
60
+ }.map { |k, v| "#{k}=#{v}" }.join('&')
61
+
62
+ url.to_s
63
+ end
64
+
65
+ def ensure_credentials
66
+ missing_variables = []
67
+ missing_variables << 'AWS_ACCESS_KEY_ID' unless @access_key
68
+ missing_variables << 'AWS_SECRET_ACCESS_KEY' unless @secret_key
69
+
70
+ unless missing_variables.empty?
71
+ raise Errors::MissingCredentialsError,
72
+ missing_variables: missing_variables.join(', ')
73
+ end
74
+ end
75
+
76
+ def s3_url?(url)
77
+ url.host == S3_HOST
78
+ end
79
+
80
+ def box_url?(url)
81
+ url.path.end_with?('.box')
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,41 @@
1
+ require 'uri'
2
+
3
+ module Vagrant
4
+ module Action
5
+ module Builtin
6
+ class BoxAdd
7
+ def call_with_s3(env)
8
+ box_url = env[:box_url]
9
+
10
+ # Non-iterable box_urls are Vagrant Cloud boxes, which we don't need
11
+ # to handle.
12
+ if box_url.respond_to?(:map!)
13
+ box_url.map! do |url|
14
+ if matched = VagrantPlugins::S3Auth::BOX_URL_MATCHER.match(url)
15
+ @logger.info('Transforming S3 box URL: #{url}')
16
+ s3_url(matched[:bucket], matched[:resource])
17
+ else
18
+ @logger.info("Not transforming non-S3 box: #{url}")
19
+ url
20
+ end
21
+ end
22
+ else
23
+ @logger.debug('Box URL #{box_url.inspect} looks like a Vagrant "
24
+ Cloud box, skipping S3 transformation...')
25
+ end
26
+
27
+ call_without_s3(env)
28
+ end
29
+
30
+ def s3_url(bucket, resource)
31
+ URI::HTTPS.build(
32
+ host: VagrantPlugins::S3Auth::S3_HOST,
33
+ path: File.join('/', bucket, resource)).to_s
34
+ end
35
+
36
+ alias_method :call_without_s3, :call
37
+ alias_method :call, :call_with_s3
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ require 'vagrant'
2
+
3
+ module VagrantPlugins
4
+ module S3Auth
5
+ module Errors
6
+ class VagrantS3AuthError < Vagrant::Errors::VagrantError
7
+ error_namespace('vagrant_s3auth.errors')
8
+ end
9
+
10
+ class MissingCredentialsError < VagrantS3AuthError
11
+ error_key(:missing_credentials)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Vagrant S3Auth plugin must be run within Vagrant.'
5
+ end
6
+
7
+ if Vagrant::VERSION < '1.5.0'
8
+ raise 'The Vagrant AWS plugin is only compatible with Vagrant 1.5+'
9
+ end
10
+
11
+ require_relative 'action'
12
+ require_relative 'errors'
13
+
14
+ module VagrantPlugins
15
+ module S3Auth
16
+ class Plugin < Vagrant.plugin(2)
17
+ name 's3auth'
18
+
19
+ description <<-DESC
20
+ Use versioned Vagrant boxes with S3 authentication.
21
+ DESC
22
+
23
+ action_hook 'authenticate-box-url', :authenticate_box_url do |hook|
24
+ setup_i18n
25
+ setup_logging
26
+
27
+ hook.append(Action.authenticate_box_url)
28
+ end
29
+
30
+ def self.setup_i18n
31
+ I18n.load_path << File.expand_path('locales/en.yml', VagrantPlugins::S3Auth.source_root)
32
+ I18n.reload!
33
+ end
34
+
35
+ def self.setup_logging
36
+ require 'log4r'
37
+
38
+ level = nil
39
+ begin
40
+ level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
41
+ rescue NameError
42
+ level = nil
43
+ end
44
+
45
+ if level
46
+ logger = Log4r::Logger.new('vagrant_s3auth')
47
+ logger.outputters = Log4r::Outputter.stderr
48
+ logger.level = level
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module S3Auth
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ en:
2
+ vagrant_s3auth:
3
+ errors:
4
+ missing_credentials: |-
5
+ Unable to read AWS credentials from the environment.
6
+
7
+ Ensure the following variables are set in your environment, or set
8
+ them at the top of your Vagrantfile:
9
+
10
+ %{missing_variables}
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ require 'vagrant-s3auth/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'vagrant-s3auth'
7
+ spec.version = VagrantPlugins::S3Auth::VERSION
8
+ spec.authors = ['Nikhil Benesch']
9
+ spec.email = ['benesch@whoop.com']
10
+ spec.summary = 'Private, versioned Vagrant boxes hosted on Amazon S3.'
11
+ spec.homepage = 'https://github.com/WhoopInc/vagrant-s3auth'
12
+ spec.license = 'All rights reserved'
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_development_dependency 'bundler', '~> 1.5'
19
+ spec.add_development_dependency 'rake'
20
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-s3auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nikhil Benesch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - benesch@whoop.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .rubocop.yml
50
+ - Gemfile
51
+ - Gemfile.lock
52
+ - LICENSE
53
+ - README.md
54
+ - Rakefile
55
+ - lib/vagrant-s3auth.rb
56
+ - lib/vagrant-s3auth/action.rb
57
+ - lib/vagrant-s3auth/action/authenticate_box_url.rb
58
+ - lib/vagrant-s3auth/action/box_add.rb
59
+ - lib/vagrant-s3auth/errors.rb
60
+ - lib/vagrant-s3auth/plugin.rb
61
+ - lib/vagrant-s3auth/version.rb
62
+ - locales/en.yml
63
+ - vagrant-s3auth.gemspec
64
+ homepage: https://github.com/WhoopInc/vagrant-s3auth
65
+ licenses:
66
+ - All rights reserved
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.0.14
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Private, versioned Vagrant boxes hosted on Amazon S3.
88
+ test_files:
89
+ - vagrant-s3auth.gemspec