vagrant-s3auth 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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