vagrant-box-s3 0.1.2 → 0.1.4
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 +4 -4
- data/README.md +14 -8
- data/lib/vagrant-box-s3/downloader.rb +11 -30
- data/lib/vagrant-box-s3/urls.rb +70 -0
- data/lib/vagrant-box-s3/utils.rb +25 -35
- data/lib/vagrant-box-s3/version.rb +1 -1
- data/lib/vagrant-box-s3.rb +5 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 633fa8c2b30bc3482894cf4f2beb0a1b7d39a8b1cf74ec93d45fb24e93de8a13
|
4
|
+
data.tar.gz: 0aed7b6dc1a38fcf0d4542ef8e38fe42c797b688071340f9e898f59267c5450b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e064c15560beb870b711bb46dce0b5af18c7c2922cf445ea5e78441e77b15befc20168e7330749f2caf5db32b2ccb527bc26446780ff8a07b3df2c5545208a5
|
7
|
+
data.tar.gz: cafd52ddd7b9b82fd0393acebaacb94d19c42cadf9fbcf8fec8e7f57c8510ac2a133e8fe775d7255d792818c78200aa869535cafac0abf96ac68912f96606849
|
data/README.md
CHANGED
@@ -11,8 +11,9 @@ Use Vagrant boxes stored in Amazon S3 private buckets.
|
|
11
11
|
|
12
12
|
## Features
|
13
13
|
|
14
|
-
This plugin works
|
15
|
-
|
14
|
+
This plugin works using the `authenticate_box_url` hook to replace S3 URLs with presigned URLs and monkey
|
15
|
+
patching `Vagrant::Util::Downloader`, extending the core Downloader class in Vagrant to override the `head` method
|
16
|
+
used when fetching box metadata URLs from S3.
|
16
17
|
|
17
18
|
## Installation
|
18
19
|
|
@@ -40,14 +41,14 @@ You can also use your credentials file to create a profile. Select the appropria
|
|
40
41
|
|
41
42
|
#### ~/.aws/credentials
|
42
43
|
|
43
|
-
[vagrant-
|
44
|
+
[vagrant-box-s3]
|
44
45
|
aws_access_key_id = AKIA...
|
45
46
|
aws_secret_access_key = ...
|
46
47
|
|
47
48
|
#### Vagrantfile
|
48
49
|
|
49
50
|
ENV.delete_if { |name| name.start_with?('AWS_') } # Filter out rogue env vars.
|
50
|
-
ENV['AWS_PROFILE'] = 'vagrant-
|
51
|
+
ENV['AWS_PROFILE'] = 'vagrant-box-s3'
|
51
52
|
|
52
53
|
Vagrant.configure("2") { |config| ... }
|
53
54
|
|
@@ -60,10 +61,11 @@ You can use any valid HTTP(S) URL for your box URL:
|
|
60
61
|
Specify the bucket name in the path of the URL. AWS has deprecated path-style URLs, but they might still be seen or used in legacy systems.
|
61
62
|
|
62
63
|
- Format: https://s3.Region.amazonaws.com/bucket-name/key-name
|
63
|
-
|
64
|
+
- Example: https://s3.eu-west-1.amazonaws.com/mybucket/mybox.box
|
65
|
+
|
64
66
|
|
65
67
|
- Format: https://s3-Region.amazonaws.com/bucket-name/keyname
|
66
|
-
|
68
|
+
- Example: https://s3-eu-west-1.amazonaws.com/bucket-name/mybox.box
|
67
69
|
|
68
70
|
#### Virtual-Hosted-Style URLs
|
69
71
|
Virtual-hosted-style URLs use the bucket name as a subdomain. This is the recommended and most commonly used format.
|
@@ -122,11 +124,15 @@ Update the current version in `lib/vagrant-box-s3/version.rb`.
|
|
122
124
|
|
123
125
|
### Dev build and test
|
124
126
|
|
125
|
-
To build the plugin, use `rake build`, this will create a file with the current version number, e.g. `pkg/vagrant-box-s3-
|
127
|
+
To build the plugin, use `rake build`, this will create a file with the current version number, e.g. `pkg/vagrant-box-s3-{VERSION}.gem`.
|
128
|
+
|
129
|
+
Remove the old version:
|
130
|
+
|
131
|
+
vagrant plugin uninstall vagrant-box-s3 --local
|
126
132
|
|
127
133
|
Testing the plugin requires installing into vagrant from the build:
|
128
134
|
|
129
|
-
vagrant plugin install ../vagrant-box-s3/pkg/vagrant-box-s3-
|
135
|
+
vagrant plugin install ../vagrant-box-s3/pkg/vagrant-box-s3-{VERSION}.gem
|
130
136
|
|
131
137
|
Then running a command that will trigger box URL related actions, such as `vagrant up`, `vagrant box update` etc. with the `--debug` flag.
|
132
138
|
|
@@ -4,43 +4,24 @@ module Vagrant
|
|
4
4
|
module Util
|
5
5
|
class Downloader
|
6
6
|
|
7
|
-
|
8
|
-
# Get URL from options, which is the last option in the list.
|
9
|
-
url = options.last
|
7
|
+
alias_method :original_head, :head
|
10
8
|
|
11
|
-
|
12
|
-
|
9
|
+
def head
|
10
|
+
if VagrantPlugins::BoxS3::Utils.is_s3_manifest(@source)
|
11
|
+
options, subprocess_options = self.options
|
12
|
+
options.unshift("-i")
|
13
|
+
options << @source
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
@logger.info("HEAD (Override): #{@source}")
|
16
|
+
result = execute_curl(options, subprocess_options)
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# Call original execute_curl (aliased).
|
21
|
-
execute_curl_without_aws_auth(options, subprocess_options, &data_proc)
|
22
|
-
|
23
|
-
rescue Aws::S3::Errors::Forbidden => e
|
24
|
-
message = "403 Forbidden: #{e.message}"
|
25
|
-
raise Errors::DownloaderError, message: message
|
26
|
-
rescue Seahorse::Client::NetworkingError => e
|
27
|
-
raise Errors::DownloaderError, message: e
|
28
|
-
end
|
29
|
-
|
30
|
-
def execute_curl_with_aws_auth(options, subprocess_options, &data_proc)
|
31
|
-
options = options.dup
|
32
|
-
url = options.find { |o| o =~ /^http/ }
|
33
|
-
|
34
|
-
if url && url.include?('amazonaws.com')
|
35
|
-
aws_auth_download(options, subprocess_options, &data_proc)
|
18
|
+
headers, _body = result.stdout.split("\r\n\r\n", 2)
|
19
|
+
headers
|
36
20
|
else
|
37
|
-
|
21
|
+
original_head
|
38
22
|
end
|
39
23
|
end
|
40
24
|
|
41
|
-
alias execute_curl_without_aws_auth execute_curl
|
42
|
-
alias execute_curl execute_curl_with_aws_auth
|
43
|
-
|
44
25
|
end
|
45
26
|
end
|
46
27
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'vagrant-box-s3/utils'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module BoxS3
|
6
|
+
class Urls
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant::plugins::box_s3')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
# Assume 'env[:box_urls]' contains the original URLs that need authentication
|
14
|
+
original_urls = env[:box_urls]
|
15
|
+
|
16
|
+
# Your logic to authenticate the URLs goes here
|
17
|
+
# This is just an example, replace it with your actual authentication mechanism
|
18
|
+
authenticated_urls = original_urls.map do |url|
|
19
|
+
presign_url(url)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Ensure the authenticated URLs are set back in the environment
|
23
|
+
env[:box_urls] = authenticated_urls
|
24
|
+
|
25
|
+
# Continue the middleware chain
|
26
|
+
@app.call(env)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Pre-sign an s3 URL, with given method.
|
32
|
+
def presign_url(url)
|
33
|
+
|
34
|
+
# Check if the URL is an S3 URL.
|
35
|
+
if !Utils.is_s3_url(url)
|
36
|
+
@logger.info("Skipping presigner for #{url}")
|
37
|
+
return url
|
38
|
+
end
|
39
|
+
|
40
|
+
@logger.info("Discovered S3 URL: #{url}")
|
41
|
+
|
42
|
+
region, bucket, key = Utils.parse_s3_url(url)
|
43
|
+
|
44
|
+
profile = ENV['AWS_PROFILE']
|
45
|
+
|
46
|
+
@logger.debug("Region: #{region}")
|
47
|
+
@logger.debug("Bucket: #{bucket}")
|
48
|
+
@logger.debug("Key: #{key}")
|
49
|
+
@logger.debug("Profile: #{profile}")
|
50
|
+
|
51
|
+
client = Aws::S3::Client.new(
|
52
|
+
profile: profile,
|
53
|
+
region: region
|
54
|
+
)
|
55
|
+
presigner = Aws::S3::Presigner.new(client: client)
|
56
|
+
|
57
|
+
presigned_url = presigner.presigned_url(
|
58
|
+
:get_object,
|
59
|
+
bucket: bucket,
|
60
|
+
key: key,
|
61
|
+
expires_in: 3600
|
62
|
+
).to_s
|
63
|
+
|
64
|
+
@logger.debug("Pre-signed URL: #{presigned_url}")
|
65
|
+
|
66
|
+
return presigned_url
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/vagrant-box-s3/utils.rb
CHANGED
@@ -7,23 +7,42 @@ module VagrantPlugins
|
|
7
7
|
|
8
8
|
# Match host style URLs, e.g.
|
9
9
|
# https://bucket-name.s3.Region.amazonaws.com/key-name
|
10
|
-
|
10
|
+
# https://bucket-name.s3-Region.amazonaws.com/key-name
|
11
|
+
S3_URL_HOST_REGEX = %r{^https?://([\w\-\.]+)\.s3[-\.]([\w\-]+)\.amazonaws\.com/([^?]+)}
|
11
12
|
|
12
13
|
# Match path style URLs e.g.
|
13
14
|
# https://s3.Region.amazonaws.com/bucket-name/key-name
|
14
15
|
# https://s3-Region.amazonaws.com/bucket-name/keyname
|
15
16
|
S3_URL_PATH_REGEX = %r{^https?://s3[-\.]([\w\-]+)\.amazonaws\.com/([^/]+)/([^?]+)}
|
16
17
|
|
18
|
+
# Check if URL matches S3 URLs.
|
19
|
+
def self.is_s3_url(url)
|
20
|
+
# Check if the URL matches either the host style or path style S3 URL
|
21
|
+
matches_host_style = !!(url =~ S3_URL_HOST_REGEX)
|
22
|
+
matches_path_style = !!(url =~ S3_URL_PATH_REGEX)
|
23
|
+
|
24
|
+
# Return true if either match is found, false otherwise
|
25
|
+
matches_host_style || matches_path_style
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if the URL is an S3 URL and the filename is 'manifest.json'
|
29
|
+
def self.is_s3_manifest(url)
|
30
|
+
uri = URI.parse(url)
|
31
|
+
filename = File.basename(uri.path)
|
32
|
+
|
33
|
+
return is_s3_url(url) && filename == 'manifest.json'
|
34
|
+
end
|
35
|
+
|
17
36
|
# Parse an s3 URL.
|
18
|
-
def self.parse_s3_url(
|
37
|
+
def self.parse_s3_url(url)
|
19
38
|
region = bucket = key = nil
|
20
|
-
if
|
21
|
-
match = S3_URL_HOST_REGEX.match(
|
39
|
+
if url =~ S3_URL_HOST_REGEX
|
40
|
+
match = S3_URL_HOST_REGEX.match(url)
|
22
41
|
region = match[2]
|
23
42
|
bucket = match[1]
|
24
43
|
key = match[3]
|
25
|
-
elsif
|
26
|
-
match = S3_URL_PATH_REGEX.match(
|
44
|
+
elsif url =~ S3_URL_PATH_REGEX
|
45
|
+
match = S3_URL_PATH_REGEX.match(url)
|
27
46
|
region = match[1]
|
28
47
|
bucket = match[2]
|
29
48
|
key = match[3]
|
@@ -32,35 +51,6 @@ module VagrantPlugins
|
|
32
51
|
return region, bucket, key
|
33
52
|
end
|
34
53
|
|
35
|
-
# Pre-sign an s3 URL, with given method.
|
36
|
-
def self.presign_url(method, url, logger)
|
37
|
-
logger.info("BoxS3: Generating signed URL for #{method.upcase}")
|
38
|
-
logger.info("BoxS3: Discovered S3 URL: #{url}")
|
39
|
-
|
40
|
-
region, bucket, key = parse_s3_url(url)
|
41
|
-
|
42
|
-
logger.debug("BoxS3: Region: #{region}")
|
43
|
-
logger.debug("BoxS3: Bucket: #{bucket}")
|
44
|
-
logger.debug("BoxS3: Key: #{key}")
|
45
|
-
|
46
|
-
client = Aws::S3::Client.new(
|
47
|
-
profile: ENV['AWS_PROFILE'],
|
48
|
-
region: region
|
49
|
-
)
|
50
|
-
presigner = Aws::S3::Presigner.new(client: client)
|
51
|
-
|
52
|
-
presigned_url = presigner.presigned_url(
|
53
|
-
method,
|
54
|
-
bucket: bucket,
|
55
|
-
key: key,
|
56
|
-
expires_in: 3600
|
57
|
-
).to_s
|
58
|
-
|
59
|
-
logger.debug("BoxS3: Pre-signed URL: #{presigned_url}")
|
60
|
-
|
61
|
-
return presigned_url
|
62
|
-
end
|
63
|
-
|
64
54
|
end
|
65
55
|
end
|
66
56
|
end
|
data/lib/vagrant-box-s3.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'vagrant'
|
2
|
+
require 'vagrant-box-s3/urls'
|
2
3
|
|
3
4
|
module VagrantPlugins
|
4
5
|
module BoxS3
|
@@ -9,6 +10,10 @@ module VagrantPlugins
|
|
9
10
|
require_relative 'vagrant-box-s3/downloader'
|
10
11
|
end
|
11
12
|
|
13
|
+
action_hook(:vagrant_box_s3_url, :authenticate_box_url) do |hook|
|
14
|
+
hook.prepend(Urls)
|
15
|
+
end
|
16
|
+
|
12
17
|
end
|
13
18
|
end
|
14
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-box-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Whiteley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-s3
|
@@ -63,12 +63,15 @@ files:
|
|
63
63
|
- README.md
|
64
64
|
- lib/vagrant-box-s3.rb
|
65
65
|
- lib/vagrant-box-s3/downloader.rb
|
66
|
+
- lib/vagrant-box-s3/urls.rb
|
66
67
|
- lib/vagrant-box-s3/utils.rb
|
67
68
|
- lib/vagrant-box-s3/version.rb
|
68
69
|
homepage: https://github.com/memiah/vagrant-box-s3
|
69
70
|
licenses:
|
70
71
|
- MIT
|
71
|
-
metadata:
|
72
|
+
metadata:
|
73
|
+
source_code_uri: https://github.com/memiah/vagrant-box-s3
|
74
|
+
bug_tracker_uri: https://github.com/memiah/vagrant-box-s3/issues
|
72
75
|
post_install_message:
|
73
76
|
rdoc_options: []
|
74
77
|
require_paths:
|